I am trying to truncate file names down to the last 4 digits (example: 941_S_5193 to become 5193). What would be the most straightforward way to loop this command to apply to roughly 600 files?

Thank you. -KM

  • how do you get the list of concerned files ? – cmak.fr Jun 27 '18 at 15:37
  • They are nested in a series of participant files located on my desktop. Example: /users/desktop/km/neuroimage/struct/941_S_5193. – klmpc Jun 27 '18 at 15:49
  • I have this: find /users/desktop/km/neuroimage/struct/ -type f -iname '[[:digit:]]*_[[:alpha:]]_*' -exec rename 's/[[:digit:]]*_[[:alpha:]]_//' {} \; – George Udosen Jun 27 '18 at 15:53
  • Let me ask the format for the names are the same as in"3 numbers_one alphabet_four numbers", if so the code i gave should help – George Udosen Jun 27 '18 at 15:54
  • 1
    Just a reminder, be careful of the filenames that could collide during renaming, e.g. ` 941_S_5193` and ` 941_P_5193` would both truncate to the same last 4 5193. – Sergiy Kolodyazhnyy Jun 27 '18 at 20:39

The rename command can do that well enough:

# Note, -n flag used for testing only, remove for actual renaming
$ ls
941_P_5191  941_P_5192  941_P_5193  941_P_5194
$ rename -n 's/^(.*)_([0-9]{4})$/$2/'  ./*
./941_P_5191 renamed as 5191
./941_P_5192 renamed as 5192
./941_P_5193 renamed as 5193
./941_P_5194 renamed as 5194

You can also do prefix removal in bash and mv within for loop:

$ for f in ./*; do echo mv "$f" "${f##*_}"; done
mv ./941_P_5191 5191
mv ./941_P_5192 5192
mv ./941_P_5193 5193
mv ./941_P_5194 5194

Note: remove echo for actual renaming to take place

  • 1
    FYI "truncating" I've always equated with removing the end of something. So I checked and removing the beginning is called "Clipping": english.stackexchange.com/questions/332906/… (+1 of course :)) – WinEunuuchs2Unix Jun 27 '18 at 23:07
  • @WinEunuuchs2Unix Interesting, never heard "clipping" being used to remove something from beginning, but nice to learn! I think "trim" could be used as well – Sergiy Kolodyazhnyy Jun 27 '18 at 23:23
  • @WinEunuuchs2Unix thank you for sharing! I never knew that truncate was only removing the end, but I guess that makes sense. – klmpc Jun 28 '18 at 14:32

I would have suggested a loop through the items in the directory using ls | tail -c 5 to list the last 4 digits of each file.

  • 2
    I need to be able to permanently rename the files, rather than just see the last 4 digits. Also, not all of the end segments begin with 5, so it would be a little less streamlined to specify each beginning digit. – klmpc Jun 27 '18 at 17:07

You gave 941_S_5193 as one file name, but few more would be helpful. I conjured up this find command that did it with a sample file called 941_S_5193:

find /users/desktop/km/neuroimage/struct/ -type f -iname '[[:digit:]]*_[[:alpha:]]_*' -exec rename -n 's/[[:digit:]]*_[[:alpha:]]_//' {} \;

Sample file names:


Using this command:

find /users/desktop/km/neuroimage/struct/ -type f -iname  '[[:digit:]]*_[[:alpha:]]_*' -exec rename -n 's/[[:digit:]]*_[[:alpha:]]_//' {} \;

Produces these change in filenames:

rename(./941_S_5194, ./5194)
rename(./923_D_5234, ./5234)
rename(./941_S_5193, ./5193)
rename(./941_S_5134, ./5134)
rename(./941_A_0034, ./0034)
rename(./941_C_9034, ./9034)



Note: Using the '-n' option in rename command lets you see what gets renamed before proceeding with the actual renaming. Remove that option when your ready to rename these files.

Steps to fully appreciate the command are:

  1. First of use this find /users/desktop/km/neuroimage/struct/ -type f -iname '[[:digit:]]*_[[:alpha:]]_*' to find the files that will be changed,
  2. If steps (1) fails then the regex does not match the filenames, tweak regex and update your question, else
  3. When it comes up as expected now add the -exec rename -n 's/[[:digit:]]*_[[:alpha:]]_//' {} \; part to the command in step (1), so it finds and shows you what gets renamed.

    find /users/desktop/km/neuroimage/struct/ -type f -iname '[[:digit:]]*_[[:alpha:]]_*' -exec rename -n 's/[[:digit:]]*_[[:alpha:]]_//' {} \;

  4. When done remove the -n option to actually rename these files. Like so:

    • find /users/desktop/km/neuroimage/struct/ -type f -iname '[[:digit:]]*_[[:alpha:]]_*' -exec rename -n 's/[[:digit:]]*_[[:alpha:]]_//' {} \;
  • The sample files that you listed all follow the correct structure (i.e. 941_S_5193, 928_F_3678 etc. with each one representing its own unique file). However, I haven't been able to get the command to run. No error comes up so I'm not entirely sure which portion isn't working, but I will try tweaking a few more times to see what I can come up with. (Thank you, btw) – klmpc Jun 27 '18 at 16:53
  • DId you use the -n option? – George Udosen Jun 27 '18 at 17:10
  • First of use this find /users/desktop/km/neuroimage/struct/ -type f -iname to find the files that will be changed, then when it comes up as expected now add the -exec rename -n 's/[[:digit:]]*_[[:alpha:]]_//' {} \; so it finds and shows you what gets renamed. When done remove the -n option to actually rename these files. – George Udosen Jun 27 '18 at 17:14
  • I did try using it with and without the -n command. Still no luck. – klmpc Jun 27 '18 at 18:48
  • DId you follow the steps I gave and if you did what result did you get from step one – George Udosen Jun 28 '18 at 8:18

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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