Bash: 如何拖尾然后复制多个文件(例如使用xargs)?
Bash: How to tail then copy multiple files (eg using xargs)?
我一直在尝试 xargs 和管道的各种组合,但我无法得到正确的结果。以前的问题并没有完全涵盖我想做的事情:
- 我在某处有一个源目录,比方说 /foo/source,混合了不同的文件
- 我只想将在源中找到的 csv 文件复制到不同的目标,例如 /foo/dest
- 但我同时还需要删除 232 header 行(例如使用 tail)
我发现我需要将 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 ...
任何指点将不胜感激!
谢谢
只需使用 find
和 exec
并将文件名复制到变量中:
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/{/}
我一直在尝试 xargs 和管道的各种组合,但我无法得到正确的结果。以前的问题并没有完全涵盖我想做的事情:
- 我在某处有一个源目录,比方说 /foo/source,混合了不同的文件
- 我只想将在源中找到的 csv 文件复制到不同的目标,例如 /foo/dest
- 但我同时还需要删除 232 header 行(例如使用 tail)
我发现我需要将 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 ...
任何指点将不胜感激!
谢谢
只需使用 find
和 exec
并将文件名复制到变量中:
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/{/}