2

I have a directory with automatically generated files that all end with the .sample extension. I would like to have a way to remove the .sample extension from them all in one terminal command.

I tried this:

mv ./{$1}*.sample ./$1

But it doesn't work because I'm definitely placing the {$1} in the wrong place or way. Can anyone point to the right direction?

Thanks in advance.

rogeriopvl
  • 360
  • 2
  • 6

5 Answers5

19
$ touch {a,b,c,"white space"}.sample

$ ls *.sample
a.sample        c.sample
b.sample        white space.sample

$ for SAMPLE in *.sample; do mv -v "$SAMPLE" "${SAMPLE%.sample}"; done
a.sample -> a
b.sample -> b
c.sample -> c
white space.sample -> white space

Edit: Also see ${parameter#word}, which deletes word from the front of parameter:

$ FILENAME=140909_stats_report.txt
$ echo "${FILENAME#140909_}"
stats_report.txt

I remember which of these I need from the positions of the # and % keys on my (UK) keyboard: # is left of % so matches on the left. Before I noticed that I had to check the man page every time :~)

These expansions also support shell wildcards:

$ echo "${FILENAME%.*}"
140909_stats_report

The # and % forms match the shortest expansion of word. You can use ## or %% for the longest match. E.g.:

$ FILENAME=140909_stats_report.txt
$ echo "${FILENAME#*_}"  # match as little as possible
stats_report.txt
$ echo "${FILENAME##*_}" # match as much as possible
report.txt

It's worth getting to grips with these expansions. There's several more, including (somewhat cranky) regex support, substrings and ways to set defaults or get variable lengths. Man bash, of course.

markdrayton
  • 2,449
  • 1
  • 20
  • 24
  • 3
    +1 - using the bash parameter substitution is the best solution. No unnecessary processes are spawned and the result is very clean. – D.Shawley Sep 12 '09 at 18:03
6
for n in *.sample ; do mv "$n" "$(basename "$n" .sample)" ; done
agsamek
  • 321
  • 1
  • 3
  • 12
5

The rename command accepts Perl expressions:

rename 's/\.sample$//' *.sample

Example:

$ ls *sample*
file0.sample  file2.sample  foo.sample.sample
file1.sample  file3.sample  with space.sample
$ rename 's/\.sample$//' *.sample
$ ls *sample*
foo.sample

On my Ubuntu system, rename is symlinked to the prename script from the perl package.

Dennis Williamson
  • 62,149
  • 16
  • 116
  • 151
1
rename '.sample' '' *.sample

On Fedora, the rename command is included in the util-linux-ng package.

Cristian Ciupitu
  • 6,396
  • 2
  • 42
  • 56
-3

One of the many way to do that:

for i in *.sample; do NEWNAME=`echo "$i" | sed 's/\.sample//'`; mv "$i" "$NEWNAME"; done
radius
  • 9,633
  • 25
  • 45
  • 1
    basename is more appropriate; besides your code is wrong: it will croak on filenames with space – niXar Sep 12 '09 at 17:37
  • Corrected for space problem – radius Sep 12 '09 at 17:44
  • 2
    This has a few other pathological problems as well. Consider what happens if a file is named '*.sample' or 'foo.sample.sample'. See Mark Drayton's solution. – D.Shawley Sep 12 '09 at 18:10
  • It fails for file names with multiple spaces, e.g. `a b.sample`. You should use `echo "$i"` instead of `echo $i`. – Cristian Ciupitu Sep 12 '09 at 19:13
  • Thanks Cristian, correted. @rogeriopvl you should probably accept markdrayton answer, so that I could suppress my not so good solution. – radius Sep 12 '09 at 19:26