0

I have a few files that I want to copy and rename with the new file names generated by adding a fixed string to each of them. E.g:

ls -ltr | tail -3
games.txt
files.sh
system.pl

Output should be:

games_my.txt
files_my.sh
system_my.pl

I am able to append at the end of file names but not before *.txt.

for i in `ls -ltr | tail -10`; do cp $i `echo $i\_my`;done

I am thinking if I am able to save the extension of each file by a simple cut as follows,

ext=cut -d'.' -f2

then I can append the same in the above for loop.

do cp $i `echo $i$ext\_my`;done

How do I achieve this?

Ajim Bagwan
  • 127
  • 3
  • 10

2 Answers2

1

You can use the following:

for file in *
do
   name="${file%.*}"
   extension="${file##*.}"
   cp $file ${name}_my${extension}
done

Note that ${file%.*} returns the file name without extension, so that from hello.txt you get hello. By doing ${file%.*}_my.txt you then get from hello.txt -> hello_my.txt.

Regarding the extension, extension="${file##*.}" gets it. It is based on the question Extract filename and extension in bash.

Community
  • 1
  • 1
fedorqui
  • 275,237
  • 103
  • 548
  • 598
  • Sorry, I forgot to mention that the file names are of different extensions and I want to retain the respective extension of each file with the rename. – Ajim Bagwan Feb 14 '14 at 11:44
  • Thanks. It works. But I don't exactly get what file%.* and file##*. are doing? What does % and ## do in this case? – Ajim Bagwan Feb 14 '14 at 12:16
  • `${file##*.}` removes everything before last `.`, so that you get the extension. `${file%.*}` returns everything before last `.`, so that you get the file name without extension. You can check http://www.gnu.org/software/bash/manual/bashref.html#Shell-Parameter-Expansion for further reference. – fedorqui Feb 14 '14 at 12:17
1

If the shell variable expansion mechanisms provided by fedorqui's answer look too unreadable to you, you also can use the unix tool basename with a second argument to strip off the suffix:

for file in *.txt
do
  cp -i "$file" "$(basename "$file" .txt)_my.txt"
done

Btw, in such cases I always propose to apply the -i option for cp to prevent any unwanted overwrites due to typing errors or similar.

It's also possible to use a direct replacement with shell methods:

  cp -i "$file" "${file/.txt/_my.txt}"

The ways are numerous :)

Alfe
  • 56,346
  • 20
  • 107
  • 159
  • Sorry, I forgot to mention that the file names are of different extensions and I want to retain the respective extension of each file with the rename – Ajim Bagwan Feb 14 '14 at 11:45
  • You could use `"${file/./_my.}"` then. It replaces just the `.` with `_my.`, so the extension stays untouched and intact. But you need to be sure then that there only is exactly one dot in the file name. – Alfe Feb 14 '14 at 13:02