Bash: 如何拖尾然后复制多个文件(例如使用xargs)?

Bash: How to tail then copy multiple files (eg using xargs)?

我一直在尝试 xargs 和管道的各种组合,但我无法得到正确的结果。以前的问题并没有完全涵盖我想做的事情:

我发现我需要将 find 的结果通过管道传输到 xargs,然后 xargs 可以对每个查找结果执行 运行 命令。但我正在努力跟踪然后复制。如果我将 tail 通过管道传输到 cp,cp 似乎没有收到文件(缺少文件操作数)。以下是我迄今为止尝试过的一些示例:

find /foo/source -name "*.csv" | xargs -I '{}' sh -c 'tail -n +232 | cp -t /foo/dest'

cp: missing file operand

find /foo/source -name "*.csv" | xargs -I '{}' sh -c 'tail -n +232 {} | cp -t /foo/dest'

结果:

cp: failed to access '/foo/dest': No such file or directory ...

find /foo/source -name "*.csv" | xargs -I '{}' sh -c 'tail -n +232 {} > /foo/dest/{}'

sh: /foo/dest/foo/source/0001.csv: No such file or directory ...

任何指点将不胜感激!

谢谢

只需使用 findexec 并将文件名复制到变量中:

find your_dir -name "*.csv" -exec sh -c 'f=""; tail -n +5 "$f" > dest_dir/$(basename "$f")' -- {} \;

请参阅 f={} 使 $f 保留文件名和完整路径。然后,将 tail 的输出重定向到文件中,从中剥离路径。

或者,根据下面的评论 (谢谢!):

find your_dir -name "*.csv" -exec sh -c 'tail -n +5 "" > dest_dir/$(basename "")' -- {} \;

您的最后一条命令已关闭,但问题是 {} 被替换为完整路径名,而不仅仅是文件名。使用 basename 命令从中提取文件名。

find /foo/source -name "*.csv" | xargs -I '{}' sh -c 'tail -n +232 {} > /foo/dest/$(basename {})'

作为 find 和 xargs 的替代方法,您可以使用 for 循环,作为 tail 的替代方法,您可以使用 sed,考虑一下:

source=/foo/source
dest=/foo/dest
for csv in $source/*.csv; do sed '232,$ !d' $csv > $dest/$(basename $csv); done

使用 GNU Parallel 你会做:

find /foo/source -name "*.csv" | parallel tail -n +232 {} '>' /foo/dest/{/}