Answers:
如@ shawn-j-goff和其他建议所建议,不要编辑在全局范围内使用ls。
只需使用一个for..do..done循环:
for f in *; do
echo "File -> $f"
done
你可以替换*使用*.txt或(与此有关的文件,目录或其它)返回一个列表中的任何其他的水珠,生成一个列表中的命令,例如$(cat filelist.txt),或者实际上与列表替换它。
在do循环内,您只需引用带有美元符号前缀的循环变量即可($f在上面的示例中如此)。您可以执行echo此操作,也可以执行其他任何操作。
例如,.xml将当前目录中的所有文件重命名为.txt:
for x in *.xml; do
t=$(echo $x | sed 's/\.xml$/.txt/');
mv $x $t && echo "moved $x -> $t"
done
甚至更好的是,如果您正在使用Bash,则可以使用Bash参数扩展而不是生成子shell:
for x in *.xml; do
t=${x%.xml}.txt
mv $x $t && echo "moved $x -> $t"
done
for循环滥用,以及尝试解析的输出的典型陷阱ls。@ DanielA.White,如果它对您没有帮助(或可能会引起误解),则可以考虑不接受此答案,因为就像您说的那样,您正在处理目录。Shawn J. Goff的答案应为您的问题提供更可靠且有效的解决方案。
ls是ls -1 | while read line; do stuff; done。至少一个空格不会中断。
mv -v您不需要echo "moved $x -> $t"
使用of的输出ls获取文件名不是一个好主意。它可能会导致故障,甚至导致危险的脚本。这是因为文件名可以包含除/和以外的任何字符null,并且ls不使用这些字符中的任何一个作为分隔符,因此,如果文件名包含空格或换行符,则会得到意外的结果。
有两种遍历文件的非常好的方法。在这里,我只是简单echo地演示了如何使用文件名进行操作;您可以使用任何东西。
第一种是使用Shell的本地Globing功能。
for dir in */; do
echo "$dir"
done
Shell扩展*/为for循环读取的单独参数。即使文件名中包含空格,换行符或其他任何奇怪的字符,for也会将每个完整名称视为一个原子单位;它不会以任何方式解析列表。
如果你想递归进入子目录,那么这不会做,除非你的shell有一些扩展通配符功能(如bash的globstar。如果你的shell不具备这些功能,或者如果你想确保你的脚本将工作在各种系统上,那么下一个选择是使用find。
find . -type d -exec echo '{}' \;
在此,该find命令将调用echo并传递文件名的参数。它为找到的每个文件执行一次此操作。与前面的示例一样,这里没有解析文件名列表。相反,文件名将完全作为参数发送。
该-exec参数的语法看起来有些滑稽。find接受第一个参数-exec,并将其作为要运行的程序,并将每个后续参数作为传递给该程序的参数。有两个特殊的参数-exec需要看。第一个是{}; 此参数将替换为之前部分find生成的文件名。第二个是;,它让我们find知道这是传递给程序的参数列表的末尾;find之所以需find要这样做,是因为您可以继续使用更多的参数,这些参数是针对执行程序的,而不是针对执行程序的。的原因\是外壳程序也处理;特别是-它代表命令的结尾,因此我们需要对其进行转义,以便外壳程序将其作为自变量find而不是自己使用。使外壳不被特别对待的另一种方法是将其用引号引起来:';'与\;此目的一样有效。
find。有魔术可以做到,甚至-exec可以解决公认的局限性。该-print0选项对于与结合使用也很有价值xargs。
如果您安装了GNU Parallel http://www.gnu.org/software/parallel/,则可以执行以下操作:
ls | parallel echo {} is in this dir
要将所有.txt重命名为.xml:
ls *.txt | parallel mv {} {.}.xml
观看GNU Parallel的介绍性视频以了解更多信息:http : //www.youtube.com/watch?v=OpaiGYxkSuQ
为什么不将IFS设置为换行符,然后捕获ls数组中的输出?将IFS设置为换行符应该可以解决文件名中包含有趣字符的问题;使用起来ls很好,因为它具有内置的排序工具。
(在测试中,我无法将IFS设置为,\n但是将其设置为换行符退格键即可,如此处其他地方所述):
例如(假设ls传入了所需的搜索模式$1):
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")
FILES=($(/bin/ls "$1"))
for AFILE in ${FILES[@]}
do
... do something with a file ...
done
IFS=$SAVEIFS
这在OS X上特别方便,例如,要捕获按创建日期(从最旧到最新)排序的文件列表,ls命令为ls -t -U -r。
\n不足。唯一有效的解决方案使用带路径名扩展的for循环或find。
这就是我的方法,但是可能有更有效的方法。
ls > filelist.txt
while read filename; do echo filename: "$filename"; done < filelist.txt
ls | while read i; do echo filename: $i; done