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.


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.

| improve this answer | |
  • 1
    This substitutes (s), space ( something ), with nothing. – ctrl-alt-delor Jul 8 '18 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).


| improve this answer | |

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
| improve this answer | |

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.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.