如何在xargs中使用替换?

时间:2017-08-26 11:55:33

标签: shell xargs

我想做的是

  1. 找到.txt分机号
  2. 的所有文件
  3. 将他们转到.dat档案
  4. 它可以这样做:

    for f in `find . -type f -name "*.txt"`; do cp $f ${f%.txt}.dat; done
    

    我想用xargs做这个,我试过这个:

    find . -type f -name "*.txt" | xargs -i cp {} ${{}%.txt}.dat
    

    我这样做的错误:

    bad substitution
    

    关于这一点,我有这些问题:

    1. 如何正确进行替换?
    2. 我很好奇xargs for loop=逐一做事时会做些事情吗?

4 个答案:

答案 0 :(得分:2)

您可以使用:

find . -type f -name "*.txt" -print0 |
xargs -0 -i bash -c 'echo cp "$1" "${1%.txt}.dat"' - '{}'

答案 1 :(得分:2)

  
      
  1. 如何正确地进行替换?
  2.   

你不能以你想要的方式使用替换,因为{}不是bash变量(只是xargs语法的一部分),因此bash不能对它进行替换。

更好的方法是创建一个完整的bash命令,并将其作为参数提供给xargs(例如xargs -0 -i bash -c 'echo cp "$1" "${1%.txt}.dat"' - '{}' - 这样你可以进行bash替换。)

  
      
  1. 我很好奇,当for循环做一个接一个的事情时,xargs会做并行的事情吗?
  2.   

是的,for循环会做后续的思考,但默认情况下xargs会一直这样做。但是,您可以使用-P的{​​{1}}选项对其进行并行化,来自xargs手册页:

xargs
     

SIGUSR1信号增加命令数                 同时运行,或SIGUSR2减少数量。您不能将其增加到实现定义的限制之上(即   显示--show-limits)。你不能                 将它折痕低于1. xargs永远不会终止它的命令;当被要求减少时,它只是等待不止一个存在   命令在开始另一个之前终止。

   -P max-procs, --max-procs=max-procs
          Run up to max-procs processes at a time; the default is 1.  If max-procs is 0, xargs will run as many processes as possible at a time.  Use the -n option or the -L  option
          with  -P;  otherwise  chances are that only one exec will be done.  While xargs is running, you can send its process a
     

不止一个人试图打印到stdout,                 除非过程在某些过程中协作,否则将以不确定的顺序生成ouptut(并且非常可能混淆)   防止这种情况的方法。使用某种锁定                 方案是防止此类问题的一种方法。通常,使用锁定方案将有助于确保正确的输出   降低性能。如果你不想忍受                 性能差异,只需安排每个进程生成一个单独的输出文件(或以其他方式单独使用   资源)。

答案 2 :(得分:0)

如果您对bash -c '...' -构造不满意,可以使用GNU Parallel:

find . -type f -name "*.txt" -print0 | parallel -0 cp {} {.}.dat

答案 3 :(得分:0)

对于此类内容,

xargs和其他工具不如 Perl 灵活。

~ ❱ find . | perl -lne '-f && ($old=$_) && s/\.txt/.dat/g && print "$old => $_"'
./dir/00.file.txt => ./dir/00.file.dat
./dir/06.file.txt => ./dir/06.file.dat
./dir/05.file.txt => ./dir/05.file.dat
./dir/02.file.txt => ./dir/02.file.dat
./dir/08.file.txt => ./dir/08.file.dat
./dir/07.file.txt => ./dir/07.file.dat
./dir/01.file.txt => ./dir/01.file.dat
./dir/04.file.txt => ./dir/04.file.dat
./dir/03.file.txt => ./dir/03.file.dat
./dir/09.file.txt => ./dir/09.file.dat

然后代替print函数使用:rename $old, $_

使用此单行,您可以重命名任何您喜欢的内容

要强制xargs使用并行模式,您应该使用-P,如:

ls *.mp4 | xargs -I xxx -P 0 ffmpeg -i xxx xxx.mp3

并行将所有.mp4个文件转换为.mp3。因此,如果您有10 mp4,那么10 ffmpeg同时运行。