Convert all file extensions to lower-case

2019-01-30 11:41发布

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-case. However, I just want to lower-case everything after the first last dot . in the name.

How can I do that in bash?

11条回答
别忘想泡老子
2楼-- · 2019-01-30 11:46

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())
查看更多
时光不老,我们不散
3楼-- · 2019-01-30 11:47

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
查看更多
够拽才男人
4楼-- · 2019-01-30 11:52

recursively for all one fine solution:

find -name '*.JPG' | sed 's/\(.*\)\.JPG/mv "\1.JPG" "\1.jpg"/' |sh

The above recursively renames files with the extension "JPG" to files with the extension "jpg"

查看更多
Summer. ? 凉城
5楼-- · 2019-01-30 11:56

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.

查看更多
劳资没心,怎么记你
6楼-- · 2019-01-30 11:58

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...

查看更多
7楼-- · 2019-01-30 11:58

If you have JDK installed you can simply compile to following:

import java.io.File;

public class FileRename {
    public static void main(String[] args) {
        long numFilesChanged = 0;
        long numFilesNotChanged = 0;

        try {
            final File directory = new File(".");
            final File[] listOfFiles = directory.listFiles();

            for (int i = 0; i < listOfFiles.length; i++) {
                if (!listOfFiles[i].isFile()) {
                    continue;
                }

                final File fileToRename = listOfFiles[i];

                final String filename = fileToRename.getName();
                final String woExtension = filename.substring(0, filename.lastIndexOf('.'));
                final String extension = filename.substring(filename.lastIndexOf('.'));

                if (extension.toLowerCase().equals(extension)) {
                    numFilesNotChanged++;
                } else {
                    numFilesChanged++;
                    fileToRename.renameTo(new File(woExtension + extension.toLowerCase()));
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println("Changed: " + numFilesChanged);
        System.out.println("Not changed:" + numFilesNotChanged);
    }
}

and run.

If you do not have JDK installed but Java installed, compile it using an online Java compiler such as: https://www.compilejava.net/ and simply put the resulting .class file in the folder where you want to rename your files and execute: java FileRename.

Feel free to reach me in case you are not familiar with Java or need help compiling and/or running.

查看更多
登录 后发表回答