Rename files using regular expression in linux

后端 未结 7 1409
北恋
北恋 2020-12-04 14:03

I have a set of files named like:

Friends - 6x03 - Tow Ross\' Denial.srt
Friends - 6x20 - Tow Mac and C.H.E.E.S.E..s         


        
相关标签:
7条回答
  • 2020-12-04 14:34

    You can use rnm:

    rnm -rs '/\w+\s*-\s*(\d)x(\d+).*$/S0\1E\2.srt/' *.srt
    

    Explanation:

    1. -rs : replace string of the form /search_regex/replace_part/modifier
    2. (\d) and (\d+) in (\d)x(\d+) are two captured groupes (\1 and \2 respectively).

    More examples here.

    0 讨论(0)
  • 2020-12-04 14:35

    Use mmv (mass-move?)

    It's simple but useful: The * wildcard matches any string (without slashes) and ? matches any character in the string to be matched. Use #X in the replace string to refer to the X-th wildcard match.

    In your case:

    mmv 'Friends - 6x?? - Tow *.srt' 'S06E#1#2.srt'
    

    Here #1#2 represent the two digits which are captured by ?? (match #1 and #2).
    So the following replacement is made:

    Friends - 6x?? - Tow *           .srt    matches
    Friends - 6x03 - Tow Ross' Denial.srt    which is replaced by
                ↓↓
            S06E03.srt
    

    mmv also offers matching by [ and ] and ;.

    You can not only mass rename, but also mass move, copy, append and link files.

    See the man page for more!

    Personally, I use it to pad numbers such that numbered files appear in the desired order when sorted lexicographically (e.g., 1 appears before 10): file_?.extfile_0#1.ext

    0 讨论(0)
  • 2020-12-04 14:42

    Not every distro ships a rename utility that supports regexes as used in the examples above - RedHat, Gentoo and their derivatives amongst others.

    Alternatives to try to use are perl-rename and mmv.

    0 讨论(0)
  • 2020-12-04 14:47

    You forgot a dot in front of the asterisk:

    rename -n 's/(\w+) - (\d{1})x(\d{2}).*$/S0$2E$3\.srt/' *.srt
    

    On OpenSUSE, RedHat, Gentoo you have to use Perl version of rename. This answer shows how to obtain it. On Arch, the package is called perl-rename.

    0 讨论(0)
  • 2020-12-04 14:48

    if your linux does not offer rename, you could also use the following:

    find . -type f -name "Friends*" -execdir bash -c 'mv "$1" "${1/\w+\s*-\s*(\d)x(\d+).*$/S0\1E\2.srt}"' _ {} \;
    

    i use this snippet quite often to perform substitutions with regex in my console.

    i am not very good in shell-stuff, but as far as i understand this code, its explanation would be like: the search results of your find will be passed on to a bash-command (bash -c) where your search result will be inside of $1 as source file. the target that follows is the result of a substitution within a subshell, where the content of $1 (here: just 1 inside your parameter-substituion {1//find/replace}) will also be your search result. the {} passes it on to the content of -execdir

    better explanations would be appreciated a lot :)

    please note: i only copy-pasted your regex; please test it first with example files. depending on your system you might need to change \d and \w to character classes like [[:digit:]] or [[:alpha:]]. however, \1 should work for the groups.

    0 讨论(0)
  • 2020-12-04 14:51

    Really cool lil diddy. find + perl + xargs + mv

    xargs -n2 makes it possible to print two arguments per line. When combined with Perl's print $_ (to print the $STDIN first), it makes for a powerful renaming tool.

    find . -type f | perl -pe 'print $_; s/input/output/' | xargs -d "\n" -n2 mv
    

    Results of perl -pe 'print $_; s/OldName/NewName/' | xargs -n2 end up being:

    OldName.ext    NewName.ext
    OldName.ext    NewName.ext
    OldName.ext    NewName.ext
    OldName.ext    NewName.ext
    

    I did not have Perl's rename readily available on my system.


    How does it work?

    1. find . -type f outputs file paths (or file names...you control what gets processed by regex here!)
    2. -p prints file paths that were processed by regex, -e executes inline script
    3. print $_ prints the original file name first (independent of -p)
    4. -d "\n" cuts the input by newline, instead of default space character
    5. -n2 prints two elements per line
    6. mv gets the input of the previous line
    0 讨论(0)
提交回复
热议问题