Bash 引号中的平铺展开
我编写了一个脚本,其中必须在用户定义的目录中找到可能包含tilde的一些文件(因此,可以使用Bash 引号中的平铺展开,bash,Bash,我编写了一个脚本,其中必须在用户定义的目录中找到可能包含tilde的一些文件(因此,可以使用user\u defined\u directory='~/foo')。这个构造看起来像 found_files=$(find "$user_defined_directory" -type f … ) 我使用引号来覆盖该路径中可能的空格,但根据手册页,在引号中波浪线扩展不起作用。我知道:运算符可能可以进行此扩展,但我不知道如何在这里使用它 正在从用户$HOME目录中的另一个配置文件获取“用户定义目录”
user\u defined\u directory='~/foo'
)。这个构造看起来像
found_files=$(find "$user_defined_directory" -type f … )
我使用引号来覆盖该路径中可能的空格,但根据手册页,在引号中波浪线扩展不起作用。我知道:
运算符可能可以进行此扩展,但我不知道如何在这里使用它
正在从用户$HOME目录中的另一个配置文件获取“用户定义目录”。它不是作为参数传递给我的脚本,而是从我编写的脚本中的另一个配置中解析出来。Tilde肯定不会在引号内展开。可能还有其他一些bash技巧,但我在这种情况下所做的是:
find ~/"$user_defined_directory" -type f
i、 e.将起始的
~/
移到引号外,并将路径的其余部分保留在引号内。您可以使用“${user\u defined\u directory/#~/$HOME}”
将字符串开头的“~”替换为当前用户的主目录。请注意,这不会处理~username/subdir
格式,只处理普通的~
。如果您需要处理更复杂的版本,则需要编写一个更复杂的转换器。在一些相当合理的假设下,这是可行的,但它远不是显而易见的代码(也不是一行代码):
在我的机器上运行时(有用户crl
),输出为:
/Users/jleffler/Documents/over enthusiastic
/Users/crl/Documents/double spaced
/work/whiffle/two spaces are better than one
/Users/jleffler
/Users/jleffler/
/Users/crl
/Users/crl/
x=[/Users/jleffler/Documents/over enthusiastic]
函数tilde_expansion
分别处理不同的情况。第一个子句处理一个值~
,并简单地替换$HOME
。第二个是妄想症:~/
被映射到$HOME/
。第三个处理~/anything
(包括一个空的'anything')。下一个案例涉及~user
。包罗万象的*
处理所有其他问题
请注意,代码做出了一个(合理的)假设,~user
不会扩展到包含任何双空格、制表符或换行符(以及其他类似空格的字符)的值。如果你不得不面对这些,生活将是地狱
请注意的答案,它解释了POSIX需要
~
扩展到当前值$HOME
,但是~user
从密码数据库扩展到主目录的值。使用eval如何user_defined_directory=$(eval echo“$user_defined_directory”)
@vaughn cato no,变量包含与之前相同的值。仅供参考:右侧有许多“相关”问题链接,其中大多数都没有帮助,包括:、。这不是一个小问题!哈,如果事情这么简单的话,我就不会在这里问了。重点是目录可能以波浪号开始,也可能不是,导致一些绝对路径。我不能,因为那样意味着转义空格和其他shell可能识别为特殊字符的内容。它比在正确的位置使用冒号更难,需要更多的代码。@vaughn cato建议的带有预解析用户定义目录的想法更好,因为它只增加了一步。非常好。可能的简化:第二种情况(\~/
)可以删除,因为第三种情况(\~/*
)可以处理。如果你使用我的答案(“${1/#~/$HOME}”
),你可以统一前三种情况(虽然在这种情况下你需要两种模式,所以它实际上不太简单,可读性也差得多)。我试图结合第二种和第三种情况,但没有得到我预期的结果,但我会再试一次,因为我可能一直在摸索。礼貌地说,我对案件的数量不满意。没有第二起案件,这对我来说是有效的。顺便说一句,它甚至可以在~joeuser
案例中使用多个空格、制表符和换行符(路径末尾的换行符除外)!尽管在expand_tilde'~(rm something)
更新的情况下,它确实存在与eval
相关的常见风险;今天的测试表明,当我在组装答案时,我遇到了“深夜编程问题”。可能会考虑使用<代码> Prtff%Q在把它交给<代码> EVA之前引用用户名。对于仅使用可移植集合中的字符的用户名来说,这应该是一个noop,但是如果我们担心恶意输入。。。
/Users/jleffler/Documents/over enthusiastic
/Users/crl/Documents/double spaced
/work/whiffle/two spaces are better than one
/Users/jleffler
/Users/jleffler/
/Users/crl
/Users/crl/
x=[/Users/jleffler/Documents/over enthusiastic]