2

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

5
  • how do you get the list of concerned files ?
    – cmak.fr
    Jun 27, 2018 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, 2018 at 15:49
  • I have this: find /users/desktop/km/neuroimage/struct/ -type f -iname '[[:digit:]]*_[[:alpha:]]_*' -exec rename 's/[[:digit:]]*_[[:alpha:]]_//' {} \; Jun 27, 2018 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 Jun 27, 2018 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. Jun 27, 2018 at 20:39

3 Answers 3

3

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

3
  • 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 :)) Jun 27, 2018 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 Jun 27, 2018 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, 2018 at 14:32
0

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.

1
  • 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, 2018 at 17:07
0

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:

941_S_5194
923_D_5234
941_S_5193
941_S_5134
941_A_0034
941_C_9034

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)

Results:

0034
5134
5193
5194
5234
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:]]_//' {} \;
16
  • 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, 2018 at 16:53
  • DId you use the -n option? Jun 27, 2018 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. Jun 27, 2018 at 17:14
  • I did try using it with and without the -n command. Still no luck.
    – klmpc
    Jun 27, 2018 at 18:48
  • DId you follow the steps I gave and if you did what result did you get from step one Jun 28, 2018 at 8:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .