【发布时间】:2020-11-30 19:07:17
【问题描述】:
以下命令尝试枚举当前目录下所有*.txt文件并一一处理:
for line in "find . -iname '*.txt'"; do
echo $line
ls -l $line;
done
为什么会出现以下错误?:
ls: invalid option -- 'e'
Try `ls --help' for more information.
【问题讨论】:
以下命令尝试枚举当前目录下所有*.txt文件并一一处理:
for line in "find . -iname '*.txt'"; do
echo $line
ls -l $line;
done
为什么会出现以下错误?:
ls: invalid option -- 'e'
Try `ls --help' for more information.
【问题讨论】:
这是一种循环文件的更好方法,因为它处理文件名中的空格和换行符:
#!/bin/bash
find . -type f -iname "*.txt" -print0 | while IFS= read -r -d $'\0' line; do
echo "$line"
ls -l "$line"
done
【讨论】:
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin16)
for-loop 将遍历提供的字符串上的每个(空格分隔)条目。
您实际上并没有执行find 命令,而是将其作为字符串提供(由for-loop 迭代)。
而不是双引号使用反引号或$():
for line in $(find . -iname '*.txt'); do
echo "$line"
ls -l "$line"
done
此外,如果您的文件路径/名称包含空格,则此方法将失败(因为 for-loop 会遍历空格分隔的条目)。相反,最好使用dogbanes answer中描述的方法。
澄清您的错误:
如前所述,for line in "find . -iname '*.txt'"; 遍历所有空格分隔的条目,它们是:
前两个不会导致错误(除了不希望的行为),但第三个在执行时会出现问题:
ls -l -iname
很多(bash)命令可以组合单个字符选项,因此-iname 与-i -n -a -m -e 相同。瞧:你的invalid option -- 'e' 错误!
【讨论】:
更紧凑的版本在文件名中使用空格和换行符:
find . -iname '*.txt' -exec sh -c 'echo "{}" ; ls -l "{}"' \;
【讨论】:
$(rm -rf ~).txt 或"; rm -rf ~; echo ".txt(双引号作为文件名的文字部分)会发生什么。
find . -iname '*.txt' -exec sh -c 'for arg in "$@"; do echo "$arg"; ls -l "$arg"; done' _ {} +
使用command substitution而不是引号来执行find而不是将命令作为字符串传递:
for line in $(find . -iname '*.txt'); do
echo $line
ls -l $line;
done
【讨论】:
$lines。一个用于“单个”,另一个用于“文件”。
for line in $(...anything...),和BashPitfalls #14回复:echo $line。对于后者,另见I just assigned a variable, but echo $variable shows something else!