2

I am trying to come up with a bash script to remove parts of a file name on CentOS. My file names are:

119903_Relinked_new_3075_FileNote_07_02_2009_JHughes_loaMeetingAndSupport_FN_205.doc
119904_relinked_new_2206_Support_Intensity_Scale_SYCH_SIS_264549.pdf
119905_relinked_new_3075_Consent_07_06_2009_DSweet_CRFA_CF_16532.docx
29908_relinked_new_2206_Assessor_Summary_Report_SERT_I_OTH_264551.pdf
009712_relinked_new_3075_Consent_07_06_2009_CWell_DPRT_check_CF_16535.pdf

I would like to remove 119903_Relinked_new_ from the file names. The end result should be:

3075_FileNote_07_02_2009_JHughes_loaMeetingAndSupport_FN_205.doc
2206_Support_Intensity_Scale_SYCH_SIS_264549.pdf
3075_Consent_07_06_2009_DSweet_CRFA_CF_16532.docx
2206_Assessor_Summary_Report_SERT_I_OTH_264551.pdf
3075_Consent_07_06_2009_CWell_DPRT_check_CF_16535.pdf

I have been trying multiple scripts but coming up short. The number before _Relinked_new_ is different in most cases and the file extensions vary across .pdf, .docx, .doc etc. Any help would be appreciated.

terdon
  • 242,166
mike87
  • 61
  • 2
  • 5

3 Answers3

5

Using the prename(1) tool (it might be called rename or prename or perl-rename depending on your system):

rename 's/[0-9]+_[rR]elinked_new_//' /path/to/dir/*

This will use a regular expression to match the pattern and replace it with nothing on the specified files.

jesse_b
  • 37,005
5

Without the rename tool, using a simple shell loop with parameter substitution to rename a file at a time:

for name in /path/to/dir/*_[rR]elinked_new_*
do
    newname=${name##*/}
    newname=${name%/*}/${newname#*_[rR]elinked_new_}
# or:
# newname=$(basename "$name")
# newname=$(dirname "$name")/${newname#*_[rR]elinked_new_}

mv -- "$name" "$newname"

done

Inside the loop, the value of newname is first computed as the filename component of the name variable (the last bit after the last slash in the pathname).

The newname variable is then modified by pretending it with the directory path and the result of removing whatever text matches the shell pattern *_[rR]elinked_new_ from the start of the filename.

The code can be simplified somewhat by first changing the current directory into the directory where the files are located:

cd /path/to/dir || exit

for name in [rR]elinked_new do newname=${name#*[rR]elinked_new} mv -- "$name" "$newname" done

Kusalananda
  • 333,661
2

This is really just a comment in response to your problem with "Argument list too long", but it started to look messy in the comment box, so now it's an answer. :)

The reason you're getting that error is that * tries to put every file in the directory onto the command line, which has length restrictions. Instead you can loop over the files (or use find to do a similar thing) and call rename on each individually:

find /path/to/dir -iname '*relinked_new_*' -exec prename 's/[0-9]+_[rR]elinked_new_//' {} \;
ilkkachu
  • 138,973
dg99
  • 2,642
  • Using the xargs variant (find /path/to/dir -iname '*relinked_new_*' -print0 | xargs -0 prename 's/[0-9]+_[rR]elinked_new_//') would be more efficient, I guess. – U. Windl Apr 19 '22 at 12:06