我有这个小脚本:
#!/bin/bash
for file in "$(ls | grep -v $0)";do
cat $file > "${file}-test"
done
在此目录中:
total 40
-rwxr-xr-x 1 root root 783 Dec 11 09:19 appendToLog.sh
-rwxr-xr-x 1 root root 3995 Dec 11 13:22 con2dd.py
-rwxr-xr-x 1 root root 362 Dec 11 13:26 dd.py
-rw-r--r-- 1 root root 566 Dec 11 13:26 dd.pyc
-rw-r--r-- 1 root root 18558 Dec 25 11:24 moshe.log
-rw------- 1 root root 0 Dec 11 09:20 nohup.out
-rwxr-xr-x 1 root root 88 Dec 25 11:28 task.sh
-rwxr-xr-x 1 root root 560 Dec 11 10:33 test.py
没关系我可以用cp
实现这一点,我想知道为什么这正是产生这个文件:
-rw-r--r-- 1 root root 24912 Dec 25 11:28 appendToLog.sh?con2dd.py?dd.py?dd.pyc?moshe.log?nohup.out?task.sh?test.py-test
没有别的。
答案 0 :(得分:2)
问题是解析ls
的输出是错误的(参见Why you shouldn't parse the output of ls(1),unix中的文件名几乎可以包含任何特殊字符,包括空格,换行符,逗号,管道符号。因为你引用了它在一个构造中ls
的输出,你有一个列表,其中所有文件连接成一个字符串,其值为"${file}-test"
,这完全不你想要做什么
还要注意ls有时会篡改您的文件名数据(在我们的例子中,它将单词之间的\n
字符转换为?
问号(可能表示无法显示的字符)。
只需使用bash
中的glob扩展列出文件并对其执行操作。
for f in *; do
[[ -e $f ]] || continue
...
done
那就是说,你可能在行尾有一些不可打印的字符(例如CRLF导入的rom Windows)
运行cat -A scriptname
它会显示脚本中的所有字符。然后,您可以转换为运行dos2unix scriptname
的类似unix的格式。