Shell “为什么可以?”$路径“/{,.}*包括"*&引用;结果如何?
我有一个bash脚本,其中我使用Shell “为什么可以?”$路径“/{,.}*包括"*&引用;结果如何?,shell,sh,glob,Shell,Sh,Glob,我有一个bash脚本,其中我使用 for x in "$path/"{.,}*; do do some stuff here done 这会在所有文件和目录上循环(这就是我想要的), 但是它也给了我一个不存在的文件*。 我在android上使用终端仿真器,所以可能会出错。 我正在寻找一个shell解决方案,因为我没有像sed这样的大多数“普通Linux”命令。如果您的shell真的是Bash(如问题最初所述) 运行以下命令: shopt -s nullglob 将禁用在没有未展开
for x in "$path/"{.,}*; do
do some stuff here
done
这会在所有文件和目录上循环(这就是我想要的),
但是它也给了我一个不存在的文件*
。
我在android上使用终端仿真器,所以可能会出错。
我正在寻找一个shell解决方案,因为我没有像sed这样的大多数“普通Linux”命令。如果您的shell真的是Bash(如问题最初所述)
运行以下命令:
shopt -s nullglob
将禁用在没有未展开匹配项的情况下保留全局的默认行为。请注意,这可能会产生令人惊讶的副作用:设置nullglob
时,ls-l*.NotFilenamesHaveThisSuffix
将与ls-l
完全相同
也就是说,你可以做得更好:
shopt -s dotglob
for x in "$path/"*; do
printf 'Processing file: %q\n' "$x"
done
由于设置了dotglob
,将查找所有隐藏的文件,而根本不需要使用{、}
习惯用法,并且还具有一贯忽略
和的好处。
如果您的Shell是
ash
或mksh
实际上,在Android设备上找到bash是很常见的。如果您有一个基线POSIX shell,那么下面的内容将更加健壮
for x in "$path"/* "$path"/.*; do
[ -e "$x" ] || continue # skip files that don't exist
basename=${x##*/} # find filename w/o path
case $basename in "."|"..") continue ;; esac # skip "." and ".."
echo "Processing $x" >&2
: ...put your logic here...
done
使用编辑器中的
{}
按钮,或在每行前面添加四个空格缩进,用于多行代码块。也就是说,您的目标只是确保隐藏文件包含在glob表达式中,对吗?告诉shell这正是您想要的更容易。(也就是说,*
在标准Linux文件系统上总是有匹配项——即使这些匹配项只是目录
和。
——所以我很好奇您的平台会得到相反的结果)…也就是说,您的shell真的很强大吗,或者它类似于busybox ash(它只支持真正的POSIX sh语法,不支持bash扩展)?看起来可能是ash或mksh,而不是bash。如果是这种情况,您可能应该调整问题的标记。至于{}按钮或缩进,谢谢,我只有一个文本框,没有编辑器按钮,我将尝试记住四个缩进。事实上,我也想要隐藏文件,平台是一个终端仿真器应用程序,其中包含posix bash的子集(如果这是正确的术语),我必须编写自己的basename。例如,我已经使用了-e解决方案,但我希望有一个解决方案不会在列表中包含。*。但我可以忍受这种行为。事实上我不明白。和。。您能解释一下为什么。*可能会出现在列表中吗?如果没有以
开头的文件,并且您的shell没有在输出中无条件地包含
或。
。(这意味着shell肯定不是bash,在全局搜索*
时会将这些作为结果包含在内),那么它就会出现在列表中。这是因为当glob不匹配时,shell的默认行为是保留不匹配的模式。这样,,ls-l*.txt
为您提供了*.txt:不存在这样的文件
,而不是像ls-l
那样没有参数,并显示当前目录中所有文件的列表,即使这些文件都不匹配全局文件。请记住,大括号扩展不会全局化--无论这些文件是否存在,都会发生这种情况。因此,{.,}*
与分别传递*
和*
完全相同,并且它们中的每一个都作为一个独立的全局表达式进行计算(如果不匹配,则留在参数列表中)…无论如何,如果您不希望*
在列表中,即使它没有扩展到任何内容,解决方案是使用shell(像bash!),支持nullglob
。