I have a bunch of files like this:


I just want to keep the first 20 characters and add a .txt extension. So in the end I should have a file with the name:


I am working on both Fedora and Solaris.


You can easily do this with a shell loop in bash:

cd /path/to/files/;
for file in *; do
    echo mv -i -- "$file" "${file:0:20}.txt"

Once you are satisfied that does what you need, remove the echo to actually rename the files:

 cd /path/to/files/;
 for file in *; do
    mv -i -- "$file" "${file:0:20}.txt"

The -i will make mv ask before overwriting if one of the new names already exists.

  • 3
    $file will include its path (/path/to/files/) which will incorrectly count towards the 20 characters.
    – Paul Evans
    Apr 21 '20 at 1:02
  • 1
    @PaulEvans oh wow, yes indeed. Fixed now, thanks.
    – terdon
    Apr 21 '20 at 8:50

Fedora and Solaris support bash shell:

With 'for' loop sometimes, without processing the path and filename individually, it will process the first 20 characters of the path mentioned but not the actual filenames.

So this will do the exact thing what you want to do, will not go to subdirectories ( if you want subdirectories to be processed, remove the '-maxdepth 0' option:

find /path/of/the/files/* -maxdepth 0 -type f| xargs -I[] bash -c 'val="[]";file=${val##*/};newfile=${file:0:20};mv $val ${val%/*}/$newfile.txt'  

The -I option in xargs replaces each filename(including path) found with "[]", and we are executing bash commands against each []->filename where we store this in $val variable and extract path and filenames , get first 20 characters of filename alone and moving it like "mv fullpath-with-filename fullpath-withoutfilename/first20charcters-of-filename".


Assuming all relevant filenames matches hhslog.* in the current directory. Then, using the Perl rename utility:

rename  's/(.{20}).*/$1.txt/' hhsLog.*

This applies the Perl substitution s/(.{20}).*/$1.txt/ to each filename. This truncates the names at 20 characters and then also adds a .txt filename suffix.

To truncate the names at the first }, use

rename  's/([^}]+).*/$1.txt/' hhsLog.*


rename -n 's/(.+?)}.*/$1.txt/' hhsLog.*

To truncate the names at the first character that is not a word character or a dot, use

rename 's/([\w.]+).*/$1.txt/' hhsLog.*

this is what worked:

for file in *
 file2=$(echo ${file} | cut -c 1-20)
 mv ${file} ${file2}.txt

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.