I have a number of directories with titles such as "20150512_101129_3016" and others with additional string following an additional underscore, such as "20150512_101129_3016_v1A" (it's not always v1A, could be v1, or V1a, etc). I would like to rename all directories such that the final string following the final underscore is removed. I'd prefer a solution that looks to remove all text following (and including) the final/3rd underscore since I am uncertain that all directory names will have the same number of characters in the text preceding the 3rd underscore.


2 Answers 2


You can do this with a simple shell loop:

for x in ./*_*_*_*; do mv -i "$x" "${x%_*}"; done

i.e. for every file whose name contains at least three underscores, rename the file, stripping off the part starting at the last underscore.

If there's a collision (e.g. both 20150512_101129_3016_v1A and 20150512_101129_3016_v1B exist), then the first file in lexicographic order is renamed to the desired target, and the second one is moved to a subdirectory, i.e. 20150512_101129_3016_v1B gets moved to 20150512_101129_3016/20150512_101129_3016_v1B after 20150512_101129_3016_v1A has been renamed to 20150512_101129_3016. To avoid this, add an extra check:

for x in ./*_*_*_*; do
  if [ -e "${x%_*}" ]; then
    echo "Not renaming $x because ${x%_*} already exists"
  mv "$x" "${x%_*}"

Alternatively, on Linux, pass the -T option to mv to make it do this check.


if the original directory names are homogeneous, i.e. follows the format of XXXXX_XXXX_XXXX (then may be followed by another _ XXXX) this code segment below, should work:

find ./ -maxdepth 1 -type d | while read dir; do
newdir=$(echo ${dir} | cut -d_ -f1-3)
# duplicate directory name protection
if [ -d ${newdir} ]
  echo "duplicate directory encountered. Appending _ to the new dir name"

#did the dir name change ? If not, do nothing
if [ ${newdir} != ${dir} ]
  mv ${dir} ${newdir}

it assumes you are in the directory which contains these subdirectories.

  • 1
    If this is a full tree then your find needs a -depth flag. You should also test to see if $dir and $newdir are different. Also test to see if $newdir already exists (eg if a_b_c_v1 and a_b_c_v1a both exist they'll both try to become a_b_c). Commented Aug 15, 2016 at 19:08
  • I tried running the most recently edited suggested code in a .sh file and returned: ./suffix.sh: line 11: unexpected EOF while looking for matching }' ./suffix.sh: line 16: syntax error: unexpected end of file
    – focusbob
    Commented Aug 15, 2016 at 19:30
  • I added a matching } to "newdir" on line 11, then returned: find: warning: you have specified the -maxdepth option after a non-option argument -type, but options are not positional (-maxdepth affects tests specified before it as well as those specified after it). Please specify options before other arguments. duplicate directory encountered. Appending _ to the new dir name mv: cannot move ./' to ./_': Device or resource busy
    – focusbob
    Commented Aug 15, 2016 at 19:32
  • I apologize a } sign went victim to an accidental backspace. Fixed it in the code. Please understand that, the improved code will add an underscore if you happen to have the same directory name with and without a 3rd _ character. I.e., if you have 20150512_101129_3016 and 20150512_101129_3016_V1a, the latter will become 20150512_101129_3016_ to protect the original
    – MelBurslan
    Commented Aug 15, 2016 at 19:43
  • Thank you. 2 more questions: 1) if I leave in the duplicate directory protection, it appears to also append "_" if there is no 3rd underscore, for example 20150512_101129_3016 becomes 20150512_101129_3016_. Is there a way to prevent this from happening (as it is not a duplicate)? 2) if I remove the protection, it appears to run fine, but returns: mv: ./' and ./.' are the same file. Also, if I have a directory name without a 3rd underscore as per above, I get mv: cannot move ./20150213_123852_3005' to a subdirectory of itself, ./20150213_123852_3005/20150213_123852_3005'
    – focusbob
    Commented Aug 15, 2016 at 20:10

You must log in to answer this question.

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