问题描述
我有一个包含路径的变量,并且想要基于该路径扩展glob模式。我想了解为什么我的尝试不起作用以及在bash中执行此操作的首选方式。
EX :我想列出主目录中的所有文本文件,或仅列出以“ test”开头的文本文件。我的失败尝试:
foo="~/"
echo $foo*.txt
echo ${foo}test*.txt
这些分别导致字符串输出~/*
和~/test*txt
。我尝试过使用引号等其他版本,但是我想这足以表明我的问题和理解水平—我是个刚入门的人。问题与使用$ HOME的波浪符号扩展有关吗?
最终,我想遍历这些文件,但我问这个问题是为了了解bash,而不仅仅是获得结果。
P.S。我敢肯定已经有答案了,但是我还没有找到任何可以帮助我理解这个案例的答案。我试图了解bash中的一般扩展顺序,但仍然不了解如何在此处应用它。
解决方法
在全局范围内,*
匹配文件名中的任何字符,但不匹配/
。因此,要在您的主目录中获取文件,请尝试:
foo=$HOME
echo $foo/*.txt
echo ${foo}/test*.txt
在奇怪的情况下,foo
($HOME
)包含shell活动字符,最好使用:
echo "$foo"/*.txt
echo "${foo}"/test*.txt
要遍历此类文件,请使用:
for fname in "$foo"/*.txt
do
# do something
done
此循环结构对于所有文件名都是安全的,即使是带有空格或其他shell激活字符的文件名也是如此。当然,这假定您的循环中的代码在适当的情况下在双引号内包含$fname
。
更新修订的问题
foo="~/"
~/
在引号内永远不会扩展:
$ foo="~/"
$ echo $foo
~/
如果您确实要使用~/
,请不要使用引号。除非您想使用~
的精美功能之一,否则通常使用$HOME
会更简单,更可靠。
如果您的最终目标是列出它们,则可以简单地选择
ls "${HOME}"/*.txt # or echo "$HOME"/*.txt
# Output
# /Users/meirgabay/file1.txt /Users/meirgabay/file2.txt /Users/meirgabay/some_file.txt
如果要遍历文件路径,请按以下步骤操作
declare -a _TXT_FILES=()
for file_path in "$HOME"/*.txt; do
echo "$file_path"
_TXT_FILES+=("$file_path")
done
echo "${_TXT_FILES[@]}"
# Output
# /Users/meirgabay/file1.txt
# /Users/meirgabay/file2.txt
# /Users/meirgabay/some_file.txt
# /Users/meirgabay/file1.txt /Users/meirgabay/file2.txt /Users/meirgabay/some_file.txt
我使用了一个数组declare -a _TXT_FILES=()
将结果存储在一个变量中。
如果您想使用~/
而不是$HOME
,也可以,只要确保不要用引号将其引起来即可。
~
字符由bash扩展,并且如果将其放在引号之间,则它将作为字符串求值,而不是扩展。
ls ~/*.txt
/Users/meirgabay/file1.txt /Users/meirgabay/file2.txt /Users/meirgabay/some_file.txt
# Output
# /Users/meirgabay/file1.txt /Users/meirgabay/file2.txt /Users/meirgabay/some_file.txt
echo ~/*.txt
/Users/meirgabay/file1.txt /Users/meirgabay/file2.txt /Users/meirgabay/some_file.txt
# Output
# /Users/meirgabay/file1.txt /Users/meirgabay/file2.txt /Users/meirgabay/some_file.txt