My camera stores photos in the following format:

DSC_0001 (2015_07_30 10_34_56 UTC).NEF

With the number after DSC_ iterating, and the brackets specifying the time and date, however all the time and date information is in the metadata so I am looking to rename all the files it produces to:

DSC_0001.NEF etc

I have looked into the rename command in bash, but cannot understand how to make it do what I want, I am wanting to change all the files in a folder.

If you could explain why what you suggest works I would be grateful so I can try and learn how to fix similar problems in the future.

NOTE: I'm using Bash if that makes a difference.


4 Answers 4


With the Perl rename tool:

rename 's/ \(.*?\)//' *.NEF

The regex should be straightforward (.*? matches the shortest string).

Tough see Why is the rename utility on Debian/Ubuntu different than the one on other distributions, like CentOS? about the two different rename commands.

  • 1
    This substitutes (s), space ( something ), with nothing. Jul 8, 2018 at 15:57

If the files are in a single folder with no subdirectories, and that folder called photos:

for pathname in photos/*(*).NEF; do
    newname=${newname%% '('*}.NEF

    printf 'Would move "%s" to "%s"\n' "$pathname" "${pathname%/*}/$newname"
    # mv -i "$pathname" "${pathname%/*}/$newname"

This would iterate over all filenames in photos whose names contained a ( and ended in ).NEF. A new filename is created by stripping the directory name off the current pathname, and then removing everything after ␣( (space and () in what remains and add .NEF at the end of the name.

The actual renaming of the files is commented out for safety.

Example output of the code above:

Would move "photos/DSC_0001 (2015_07_30 10_34_56 UTC).NEF" to "photos/DSC_0001.NEF"

If the files are located somewhere in a larger directory structure:

find photos -type f -name '*(*).NEF' -exec sh -c '
    for pathname do
        newname=${newname%% \(*}.NEF

        printf "Would move "%s" to "%s"\n" "$pathname" "${pathname%/*}/$newname"
        # mv -i "$pathname" "${pathname%/*}/$newname"
    done' sh {} +

The only difference here is the manner in which the pathnames to the relevant files are generated for the loop. In this case, find will pass batches of found pathnames to the loop, but the loop itself is the same as it was in the first bit of this answer (with some minor modifications to quoting).



If there is an space-parenthesis (() pair in all file names (and not in the path) you can use:

mv "$f" "${f%% (*}.NEF"

To loop over all files do:

$ for f in dir/*\(*\).NEF; do [ -f "$f" ] && mv "$f" "${f%% (*}.NEF"; done

You have to be in the directory where the files are

let a=0; for i in *.NEF; do let a=a+1; b=`basename $PWD`; c=`printf %04d$b.NEF $a`; mv $i $c; done

To rename all in same time.

You must log in to answer this question.