我想跑步:
./a.out < x.dat > x.ans
对于目录A中的每个* .dat文件。
当然,可以通过bash / python /任何脚本来完成,但是我喜欢写性感的单行代码。我所能达到的是(仍然没有任何标准输出):
ls A/*.dat | xargs -I file -a file ./a.out
但是xargs中的-a无法理解replace-str'file'。
谢谢你的帮助。
我想跑步:
./a.out < x.dat > x.ans
对于目录A中的每个* .dat文件。
当然,可以通过bash / python /任何脚本来完成,但是我喜欢写性感的单行代码。我所能达到的是(仍然没有任何标准输出):
ls A/*.dat | xargs -I file -a file ./a.out
但是xargs中的-a无法理解replace-str'file'。
谢谢你的帮助。
Answers:
首先,不要将ls
输出用作文件列表。使用shell扩展或find
。有关ls + xargs滥用的潜在后果以及正确xargs
使用示例,请参见下文。
如果您只想处理下方的文件A/
,那么一个简单的for
循环就足够了:
for file in A/*.dat; do ./a.out < "$file" > "${file%.dat}.ans"; done
ls | xargs
呢?这是一个示例,说明如果ls
与配合使用,情况可能会变得很糟xargs
。请考虑以下情形:
首先,让我们创建一些空文件:
$ touch A/mypreciousfile.dat\ with\ junk\ at\ the\ end.dat
$ touch A/mypreciousfile.dat
$ touch A/mypreciousfile.dat.ans
查看文件,它们什么都不包含:
$ ls -1 A/
mypreciousfile.dat
mypreciousfile.dat with junk at the end.dat
mypreciousfile.dat.ans
$ cat A/*
使用xargs
以下命令运行魔术命令:
$ ls A/*.dat | xargs -I file sh -c "echo TRICKED > file.ans"
结果:
$ cat A/mypreciousfile.dat
TRICKED with junk at the end.dat.ans
$ cat A/mypreciousfile.dat.ans
TRICKED
因此,您已经设法覆盖了mypreciousfile.dat
和mypreciousfile.dat.ans
。如果这些文件中有任何内容,则将其删除。
xargs
:正确的使用 方法 find
如果您要坚持使用xargs
,请使用-0
(以空字符结尾的名称):
find A/ -name "*.dat" -type f -print0 | xargs -0 -I file sh -c './a.out < "file" > "file.ans"'
注意两件事:
.dat.ans
结尾创建文件;"
。可以通过不同的Shell调用方式解决这两个问题:
find A/ -name "*.dat" -type f -print0 | xargs -0 -L 1 bash -c './a.out < "$0" > "${0%dat}ans"'
find ... -exec
find A/ -name "*.dat" -type f -exec sh -c './a.out < "{}" > "{}.ans"' \;
同样,这会产生.dat.ans
文件,如果文件名包含,则会损坏"
。为此,请使用bash
并更改其调用方式:
find A/ -name "*.dat" -type f -exec bash -c './a.out < "$0" > "${0%dat}ans"' {} \;
zsh
用作外壳(和SH_WORD_SPLIT未设置),所有讨厌的特殊情况下(白色空间“,在文件名等)需要不被认为是琐碎的。for file in A/*.dat; do ./a.out < $file > ${file%.dat}.ans ; done
作品在所有情况下。
find
。
尝试执行以下操作(语法可能会有所不同,具体取决于您使用的shell):
$ for i in $(find A/ -name \*.dat); do ./a.out < ${i} > ${i%.dat}.ans; done
somefile.dat.dat
,并将所有输出重定向到单个文件。
somefile.dat.ans
输出的东西看起来不太好。
-type file
会很好(不能< directory
),这会使不寻常的文件名童话变得可悲。
对于简单模式,for循环是合适的:
for file in A/*.dat; do
./a.out < "${file}" > "${file%.dat}.ans" # Never forget the QUOTES!
done
对于更复杂的情况,您需要另一个实用程序来列出文件(zsh或bash 4具有足够强大的模式,您几乎不需要找到它们,但是如果要保留在POSIX shell内或使用破折号之类的快速shell,则将需要查找任何内容非平凡的),而阅读最合适:
find A -name '*.dat' -print | while IFS= read -r file; do
./a.out < "${file}" > "${file%.dat}.ans" # Never forget the QUOTES!
done
这将处理空格,因为read(默认情况下)是面向行的。它不会处理换行符,也不会处理反斜杠,因为默认情况下,它会解释转义序列(实际上允许您传递换行符,但是find无法生成该格式)。许多外壳程序都具有-0
读取选项,因此您可以处理所有字符,但不幸的是,它不是POSIX。
使用GNU并行:
parallel ./a.out "<{} >{.}.ans" ::: A/*.dat
增加的好处:您可以并行完成处理。
观看介绍性视频以了解更多信息:http : //www.youtube.com/watch?v=OpaiGYxkSuQ
我认为您至少需要在xargs中进行外壳程序调用:
ls A/*.dat | xargs -I file sh -c "./a.out < file > file.ans"
编辑:应该注意的是,当文件名包含空格时,此方法不起作用。不能工作 即使您使用find -0和xargs -0来使xargs正确理解空格,-c shell调用也会破坏它们。但是,OP明确要求使用xargs解决方案,这是我想到的最好的xargs解决方案。如果文件名中的空格可能是一个问题,请使用find -exec或Shell循环。
ls
输出诸如空格之类的东西而不会逃避,这就是问题所在。
ls
是不好的。但是xargs
可以安全地与find一起使用-请参阅我的答案中的第二个建议。