Convert all file extensions to lower-case

前端 未结 11 1928
生来不讨喜
生来不讨喜 2020-12-07 14:06

I\'m trying to lower-case all my extensions regardless of what it is. So far, from what I\'ve seen, you have to specify what file extensions you want to convert to lower-cas

相关标签:
11条回答
  • 2020-12-07 14:26

    So, these solutions that look like line noise are nice and all, but this is easy to do from the python REPL (I know the OP asked for bash, but python is installed on a lot of systems that have bash these days...):

    import os
    files = os.listdir('.')
    for f in files:
        path, ext = os.path.splitext(f)
        if ext.isupper():
            os.rename(f, path + ext.lower())
    
    0 讨论(0)
  • 2020-12-07 14:29

    I was looking for a simple way to do this (without having to think about it) but I finally ended up thinking it through and came up with this (admittedly, way after the original post)

    find . -name \\*.JPG -print -exec rename s/.JPG/.jpg/ {} \\;
    

    I ran it on about 60 thousand files and it worked fine but, of course, you can use the -n option to 'rename' if you want to test it out first.

    0 讨论(0)
  • 2020-12-07 14:32

    This will do the job for your '.mp3's - but only in the working directory - however is able to consume filenames with whitespace:

    for f in *.[mM][pP]3; do mv "$f" "${f%.*}.mp3"; done
    

    Correction:

    for f in *.[mM][pP]3; do [[ "$f" =~ \.mp3$ ]] || mv "$f" "${f%.*}.mp3"; done
    
    0 讨论(0)
  • 2020-12-07 14:33

    If you have mmv (=move multiple files) installed and your filenames contain at most one dot, you can use

    mmv -v "*.*" "#1.#l2"
    

    It does not get more than one dot right (since the matching algo for * is not greedy in mmv), however, it handles () and ' correctly. Example:

    $ mmv -v "*.*" "#1.#l2"
    FOO.BAR.MP3 -> FOO.bar.mp3 : done
    foo bar 'baz' (CD 1).MP3 -> foo bar 'baz' (CD 1).mp3 : done
    

    Not perfect, but much easier to use and remember than all the find/exec/sed stuff.

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

    This is shorter but more general, combined from other's answer:

    rename 's/\.([^.]+)$/.\L$1/' *
    

    Simulation

    For simulation, use -n, i.e. rename -n 's/\.([^.]+)$/.\L$1/' *. This way you can see what will be changed before the real changes being performed. Example output:

    Happy.Family.GATHERING.JPG renamed as Happy.Family.GATHERING.jpg
    Hero_from_The_Land_Across_the_River.JPG renamed as Hero_from_The_Land_Across_the_River.jpg
    rAnD0m.jPg1 renamed as rAnD0m.jpg1
    

    Short explanation about the syntax

    • The syntax is rename OPTIONS 's/WHAT_TO_FIND_IN_THE_NAME/THE_REPLACEMENT/' FILENAMES
    • \.([^.]+)$ means sequence of anything but dot ([^.]) at the end of the string ($), after dot (\.)
    • .\L$1 means dot (\.) followed by lowercase (\L) of 1st group ($1)
    • First group in this case is the extension ([^.]+)
    • You better use single quote ' instead of double quote " to wrap the regex to avoid shell expansion
    0 讨论(0)
  • 2020-12-07 14:36

    Well, you could use this snippet as the core of whatever alternative you need:

    #!/bin/bash
    
    # lowerext.sh    
    
    while read f; do
        if [[ "$f" = *.* ]]; then
            # Extract the basename
            b="${f%.*}"
    
            # Extract the extension
            x="${f##*.}"
    
            # Convert the extension to lower case
            # Note: this only works in recent versions of Bash
            l="${x,,}"
    
            if [[ "$x" != "$l" ]]; then
                mv "$f" "$b.$l"
            fi
        else
            continue
        fi
    done
    

    Afterwards, all you need to do is feed a list of the files you need to rename to its standard input. E.g. for all files under the current directory and any subdirectory:

    find -type f | lowerext.sh
    

    A small optimization:

    find -type f -name '*.*' | lowerext.sh
    

    You will have to be more specific if you need a more concrete answer than this...

    0 讨论(0)
提交回复
热议问题