Modifying replace string in xargs

前端 未结 8 1350
梦毁少年i
梦毁少年i 2021-01-30 01:43

When I am using xargs sometimes I do not need to explicitly use the replacing string:

find . -name \"*.txt\" | xargs rm -rf

In oth

相关标签:
8条回答
  • 2021-01-30 02:00

    the files should be renamed/moved from <name>.txt to /foo/<name>.bar.txt

    You can use rename utility, e.g.:

    rename s/\.txt$/\.txt\.bar/g *.txt
    

    Hint: The subsitution syntax is similar to sed or vim.

    Then move the files to some target directory by using mv:

    mkdir /some/path
    mv *.bar /some/path
    

    To do rename files into subdirectories based on some part of their name, check for:

    -p/--mkpath/--make-dirs Create any non-existent directories in the target path.


    Testing:

    $ touch {1..5}.txt
    $ rename --dry-run "s/.txt$/.txt.bar/g" *.txt
    '1.txt' would be renamed to '1.txt.bar'
    '2.txt' would be renamed to '2.txt.bar'
    '3.txt' would be renamed to '3.txt.bar'
    '4.txt' would be renamed to '4.txt.bar'
    '5.txt' would be renamed to '5.txt.bar'
    
    0 讨论(0)
  • 2021-01-30 02:11

    If you're allowed to use something other than bash/sh, AND this is just for a fancy "mv"... you might try the venerable "rename.pl" script. I use it on Linux and cygwin on windows all the time.

    http://people.sc.fsu.edu/~jburkardt/pl_src/rename/rename.html

    rename.pl 's/^(.*?)\.(.*)$/\1-new_stuff_here.\2/' list_of_files_or_glob
    

    You can also use a "-p" parameter to rename.pl to have it tell you what it WOULD HAVE DONE, without actually doing it.

    I just tried the following in my c:/bin (cygwin/windows environment). I used the "-p" so it spit out what it would have done. This example just splits the base and extension, and adds a string in between them.

    perl c:/bin/rename.pl -p 's/^(.*?)\.(.*)$/\1-new_stuff_here.\2/' *.bat
    
    rename "here.bat" => "here-new_stuff_here.bat"
    rename "htmldecode.bat" => "htmldecode-new_stuff_here.bat"
    rename "htmlencode.bat" => "htmlencode-new_stuff_here.bat"
    rename "sdiff.bat" => "sdiff-new_stuff_here.bat"
    rename "widvars.bat" => "widvars-new_stuff_here.bat"
    
    0 讨论(0)
  • 2021-01-30 02:12

    If you have GNU Parallel http://www.gnu.org/software/parallel/ installed you can do this:

    find . -name "*.txt" | parallel 'ext="{/}" ; mv -- {} foo/{/.}.bar.${ext##*.}'
    

    Watch the intro videos for GNU Parallel to learn more: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

    0 讨论(0)
  • 2021-01-30 02:17

    Inspired by an answer by @justaname above, this command which incorporates Perl one-liner will do it:

    find ./ -name \*.txt | perl -p -e 's/^(.*\/(.*)\.txt)$/mv $1 .\/foo\/$2.bar.txt/' | bash

    0 讨论(0)
  • 2021-01-30 02:18

    In cases like this, a while loop would be more readable:

    find . -name "*.txt" | while IFS= read -r pathname; do
        base=$(basename "$pathname"); name=${base%.*}; ext=${base##*.}
        mv "$pathname" "foo/${name}.bar.${ext}"
    done
    

    Note that you may find files with the same name in different subdirectories. Are you OK with duplicates being over-written by mv?

    0 讨论(0)
  • 2021-01-30 02:21

    It is possible to do this in one pass (tested in GNU) avoiding the use of the temporary variable assignments

    find . -name "*.txt" | xargs -I{} sh -c 'mv "$1" "foo/$(basename ${1%.*}).new.${1##*.}"' -- {}
    
    0 讨论(0)
提交回复
热议问题