我必须连接一组文件。目录结构如下:
root/features/xxx/multiple_files... -> root/xxx/single_file
我写的(并且工作正常):
for dirname in $(ls -d root/features/*|awk -F/ '{print $NF}');do;mkdir root/${dirname};cat root/features/${dirname}/* > root/${dirname}/final.txt;done
但是当我通过sh shell运行相同的东西时
/bin/sh -c "for dirname in $(ls -d root/features/*|awk -F/ '{print $NF}');do;mkdir root/${dirname};cat root/features/${dirname}/* > root/${dirname}/final.txt;done"
它给了我错误:
/bin/sh: -c: line 1: syntax error near unexpected token `201201000'
/bin/sh: -c: line 1: `201201000'
我的进程在运行任何命令之前总是附加/ bin / sh -c。有什么建议可能会出错吗?还有其他方法吗?我在这方面花了很长时间,没有取得太大进展!
编辑:
`ls -d root/features/*|awk -F/ '{print $NF}'
返回
201201
201201000
201201001
201201002
201201003
201201004
201201005
201201006
201201007
201202000
201205000
201206000
201207000
201207001
201207002
答案 0 :(得分:3)
始终将sh -c 'cmd1 | cmd2'
与单引号一起使用。
始终使用sh -eu -xv -c 'cmd1 | cmd2'
进行调试。
如果您的代码是特定于Bash的(请参阅流程替换,......),请始终使用bash -c 'cmd1 | cmd2'
。
在;
中的do
后删除for ... ; do; mkdir ...
。
单引号中的单引号可以逃避:' --> '\''
。
(有时只是格式化你的代码会澄清很多。)
应用于你的命令,这应该看起来像这样......
# test version
/bin/sh -c '
for dirname in $(ls -d /* | awk -F/ '\''{print $NF}'\''); do
printf "%s\n" "mkdir root/${dirname}";
printf "%s\n" "cat root/features/${dirname}/* > root/${dirname}/final.txt";
echo
done
' | nl
# test version using 'printf' instead of 'ls'
sh -c '
printf "%s\000" /*/ | while IFS="" read -r -d "" file; do
dirname="$(basename "$file")"
printf "%s\n" "mkdir root/${dirname}";
printf "%s\n" "cat root/features/${dirname}/* > root/${dirname}/final.txt";
echo
done
' | nl
答案 1 :(得分:1)
我让这个在我在盒子上设置的小测试环境中运行。事实证明它不喜欢双引号。我遇到的问题是围绕awk声明的引用...如果你用双引号括起来它打印整个东西.....我用cut来得到想要的结果,但我的猜测是你必须要将-f arg更改为3而不是2 ..我认为。
/bin/sh -c 'for dirname in $(ls -d sh_test/* | awk -F/ '\''{print $NF}'\''); do mkdir sh_test_root/${dirname}; cat sh_test/${dirname}/* > sh_test_root/${dirname}/final.txt;done'
编辑:由nadu提出的测试编辑,它工作正常。以上反映了这种变化。