I have directories I want to rename, for example: 10-00017_S9_L001_plasmidspades_careful

I want to rename them to just the 10-00017_S9_L001 part

I've tried to use the cut command echo "$filename" | cut -d'_' -f3, however that leaves me with just the L001 part of the filename.

Obviously I could just rename them all manually, but there are hundreds of directories and I have not got the time.

Is there a way to use the cut command to get everything before the specific instance of the delimiter, or indeed anything else I could use?


The best solution is to use rename (Debian) or prename (RedHat) (same command, different name)(these packages could have to be added from the standard distro repos). It uses regular expressions (Perl-style). For instance, trying to be a bit strict on the match:

rename -n 's/(\d+_\d+_S\d_L\d+)_.+/$1/' *

or a more lenient:

rename -n 's/(.+_.+_.+_.+)_.+/$1/' *

With -n it just shows what it would do, remove (or better, replace by -v) for actual execution.

Note the single quotes around the pattern to avoid bash substitution on backslashes and dollars.

  • In is Larry Wall's rename. Some systems have a different rename. rename is sed for file-names. – ctrl-alt-delor Nov 16 '18 at 13:45

A rather low tech solution:

  • Use ls or find to create a list of directory in a file
  • Use an editor you are familiar with to replace each line (that just contains oldname by mv oldname newname)
  • Execute the script:

    . list_of_moves

    (note leading dot-space)


Put all directories in one file and execute below command to get it renamed

awk '{print "mv"  " "   $1  " " substr($1,1,16)}' filename | sh

Tested for above mentioned dirtectoy and it worked fine

echo "10-00017_S9_L001_plasmidspades_careful" | awk '{print "mv"  " "   $1  " " substr($1,1,16)}' | sh

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.