I wrongly added .dcm extension on all files on my Mac, which resulted in failure to log in on my iCloud and the storage of my key chains.

Having been so desperate to find out a solution to restore their original file extensions, but I only found answers to replace .abc with .def extensions, which is not I want. I want to remove all the redundant .dcm extension added on every file.

Is there a way to just delete the .dcm extensions on all files (recursively)?

These are the solutions to replacing file-extions I found:

for file in *.abc; do mv "$file" "${file%.abc}"; done
for old in *.abc; do mv $old basename $old .abc.ef; done

They are either not recursive or Bash (3.2x) says "bad substitution" / "command not found".

  • 1
    I'm curious what answers you found that explain how to replace something, but which would not allow you to just delete the extension? – slhck Aug 21 '17 at 15:49
  • several...since those questions are about how to replace one file extension with another such as .abc to .def, the answers are like "for file in *.abc; do mv "$file" "${file%.abc}.def"; done – Yaqian Huang Aug 21 '17 at 16:10
  • 1
    Did it occur to you to simply remove the .def from the examples you found? Bash doesn't replace anything here… it deletes .abc and then you add .def. So you could have just left out the "add .def" part. – slhck Aug 21 '17 at 16:11
  • Yep, and bash says bad substitution – Yaqian Huang Aug 21 '17 at 16:12
  • and this isn't recursive as well – Yaqian Huang Aug 21 '17 at 16:13

This should do it:

find / -type f -name '*.dcm' -exec sh -c 'mv -- "$0" "${0%.dcm}"' {} \;

The command:

  • Recurses from /
  • Finds every file named *.dcm
  • Executes a small subshell call with one argument, the filename ({})
  • … which renames the file ($0) using mv
  • deleting the shortest match (%) of .dcm using string manipulation

Put an echo in front of mv to see what it would do.

If you want to work without the subshell, you can pipe to while:

find / -type f -name '*.dcm' -print0 | while IFS= read -r -d '' filename; do
  mv -- "$filename" "${filename%.dcm}"
|improve this answer|||||
  • Thanks a lot! I'll play with it a bit more. And I just found another working solution: find /path/to/your/files -name '*.dcm' | while read fname; do mv "$fname" "${fname%.dcm}" done – Yaqian Huang Aug 21 '17 at 16:17
  • This is also good, but not that robust. See my answer for a better solution that handles all kinds of possible whitespace in filenames. (Bash is weird, but it's required: unix.stackexchange.com/questions/9496/…) – slhck Aug 21 '17 at 16:23
  • there's a line during the execution says: override r-------- Apple/staff for /Users/Apple/Library/Keychains/.fl0D1D1BA9? (y/n [n]) I don't understand the content. Guess I should hit [n]? – Yaqian Huang Aug 22 '17 at 3:27
  • Yep, and the one with echo works awesome! – Yaqian Huang Aug 22 '17 at 4:30

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.