我正在尝试列出目录中的文件,并在Mac OS X提示符下对它们执行某些操作。
它应该是这样的:对于f in $(ls -1);回声$ f;完成
如果我的名字中没有空格的文件(fileA.txt,fileB.txt),回声工作正常。 如果文件名称中包含空格(“文件A.txt”,“文件B.txt”),我会得到4个字符串(文件,A.txt,文件,B.txt)。
我试过引用列表命令,但它只是改变了问题。
如果我这样做:f in $(ls -1);回声$ f; DONE 我得到:文件A.txt \ nfile B.txt
(它显示正确,但它是一个单独的字符串,我需要分开2行。
答案 0 :(得分:12)
尽可能远离ls。使用findutils包中的find。
find /target/path -type f -print0 | xargs -0 your_command_here
-print0
将导致find输出由NUL字符分隔的名称(ASCII为零)。 xargs的-0
参数告诉它期望由NUL字符分隔的参数,所以一切都会正常工作。
将/target/path
替换为文件所在的路径。
-type f
只能查找文件。对目录使用-type d
,或者完全省略以获取目录。
将your_command_here
替换为您将用于处理文件名的命令。 (注意:如果你使用echo为your_command_here从shell运行它,你将获得一行上的所有东西 - 不要被那个shell工件搞糊涂,xargs无论如何都会做正确的事情。)
编辑:或者(或者如果你没有xargs),你可以使用效率低得多的
find /target/path -type f -exec your_command_here \{\} \;
\{\} \;
是{} ;
的转义符,它是当前处理文件的占位符。然后,find将调用your_command_here
并将{} ;
替换为文件名,并且由于your_command_here
将由find而不是shell启动,因此空格无关紧要。
第二个版本的效率会降低,因为find会为找到的每个文件启动一个新进程。 xargs足够智能,可以将命令传递给新启动的进程,如果它能够确保安全的话。如果您有选择,请更喜欢xargs版本。
答案 1 :(得分:10)
for f in *; do echo "$f"; done
应该做你想做的事。您为什么使用ls
代替*
?
通常,处理shell中的空格是PITA。看看$IFS
变量,或者更好的是Perl,Ruby,Python等。
答案 2 :(得分:2)
以下是 derobert 讨论的使用$ IFS的答案 http://www.cyberciti.biz/tips/handling-filenames-with-spaces-in-bash.html
答案 3 :(得分:0)
您可以将参数传递给read
。例如,cat
目录中的所有文件:
ls -1 | while read FILENAME; do cat "$FILENAME"; done
这意味着你仍然可以像问题一样使用ls
,或者使用任何其他产生$IFS
分隔输出的命令。
while
循环可以更容易地为参数做几件事,并且在我看来使复杂处理更具可读性。一个人为的例子:
ls -1 | while read FILE
do
echo 1: "$FILE"
echo 2: "$FILE"
done
答案 4 :(得分:0)
看--quoting-style选项。 例如, - quoting-style = c会产生:
$ ls --quoting-style = c
“file1”“file2”“dir one”
答案 5 :(得分:-1)
查看xargs的联机帮助页:
它的工作原理如下:
ls -1 /tmp/*.jpeg | xargs rm