1

我必须连接一组文件。目录结构是这样的:

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
4

2 回答 2

5

始终使用sh -c 'cmd1 | cmd2'单引号。

始终用于sh -eu -xv -c 'cmd1 | cmd2'调试。

bash -c 'cmd1 | cmd2'如果您的代码是特定于 Bash 的(参见进程替换,...​​),请始终使用。

;之后删除。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
于 2013-02-01T14:51:28.350 回答
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 提出的经过测试的编辑,效果很好。以上反映了这种变化。

于 2013-02-01T03:25:52.493 回答