64

I have a lot of files that have a shared pattern in their name that I would like to remove. For example I have the files, "a_file000.tga" and "another_file000.tga". I would like to do an operation on those files that would remove the pattern "000" from their names resulting in the new names, "a_file.tga" and "another_file.tga".

sth
  • 222,467
  • 53
  • 283
  • 367
resolveaswontfix
  • 1,115
  • 2
  • 10
  • 11

5 Answers5

98

Bash can do sed-like substitutions:

for file in *; do mv "${file}" "${file/000/}"; done
Dennis Williamson
  • 346,391
  • 90
  • 374
  • 439
  • Works nicely on OS X (10.6.8). Handy and succinct. Thanks. – jamesnotjim Apr 03 '13 at 15:42
  • 1
    Nice, can you explain the function of "{" ? – efrem Feb 14 '16 at 15:07
  • @efrem: The curly braces are an optional delimiter for variable names and are necessary for parameter expansions. See the [Bash Manual](https://www.gnu.org/software/bash/manual/bashref.html#Shell-Parameter-Expansion) for more information. – Dennis Williamson Feb 14 '16 at 20:22
  • 2
    For documentation on this functionality please see section 3.5.3 [Shell Parameter Expansion](https://www.gnu.org/software/bash/manual/bashref.html#Shell-Parameter-Expansion) from _Bash Reference Manual_, look for `${parameter/pattern/string}`. More detailed examples of parameter substitution could be found in section 10.2 [Parameter Substitution](http://www.tldp.org/LDP/abs/html/parameter-substitution.html) from _Advanced Bash-Scripting Guide_. – Pavel Zubkou Mar 31 '16 at 12:21
  • 1
    @irnc: Another: [Parameter Expansion](http://mywiki.wooledge.org/BashGuide/Parameters?#Parameter_Expansion) – Dennis Williamson Mar 31 '16 at 17:46
  • 1
    Best answer, IMO. – John Manko Oct 16 '17 at 05:14
  • Works like a charm. Thanks – Luis H Cabrejo Mar 07 '21 at 00:44
84

Try this (this works in plain old Bourne sh as well):

for i in *000.tga
do
    mv "$i" "`echo $i | sed 's/000//'`"
done

Both arguments are wrapped in quotes to support spaces in the filenames.

mouviciel
  • 66,855
  • 13
  • 106
  • 140
  • 2
    +1 for most portable solution (and because I'm running too low on upvotes to keep upvoting _all_ the good answers). – Chris Lutz Sep 30 '09 at 19:38
  • 1
    Portable, but slow and buggy (`echo $i` is itself buggy for the reasons described in [I just assigned a variable, but `echo $variable` shows something else](https://stackoverflow.com/questions/29378566/i-just-assigned-a-variable-but-echo-variable-shows-something-else), and running a separate copy of `sed` for each name is _very_ slow) – Charles Duffy Jun 20 '23 at 13:37
  • 1
    ...also, backticks are bad form -- `$( )` has been standardized as part of the POSIX sh standard (which supersedes 1970s Bourne) since the early 1990s; there's no good reason to keep using the old form that's hard to nest and changes the meaning of backslashes within them. – Charles Duffy Jun 20 '23 at 13:38
13

A non-bash solution, since I know two speedy posters have already covered that:

There's an excellent short perl program called rename which is installed by default on some systems (others have a less useful rename program). It lets you use perl regex for your renaming, e.g:

rename 's/000//' *000*.tga
Cascabel
  • 479,068
  • 72
  • 370
  • 318
4

Use rename, maybe you need to install it on linux, Its python script

rename (option) 's/oldname/newname' ...

so you can use it like

rename -v 's/000//' *.tga

that means we are instructing to replace all files with .tga extension in that folder to replace 000 with empty space. Hope that works

You can check this link for more info and here

Dhruv Pal
  • 849
  • 2
  • 10
  • 25
3
#!/bin/bash
ls | while read name; do
  echo mv $name ${name/$1//}
done
DigitalRoss
  • 143,651
  • 25
  • 248
  • 329
  • @Laurence Gonsalves: using shell wildcards expand the command line, and there's a not-so big limit there. "while read" avoids that – Javier Sep 30 '09 at 19:54
  • @Laurence: This is also much more extensible. It's commonly used with `find` on the front. – Cascabel Sep 30 '09 at 20:02
  • 1
    `while read` is an improvement (if it were used correctly, with an empty `IFS` and `-r`, and `-d ''` and a NUL-delimited input stream), but `ls` is the opposite. See [Why you shouldn't parse the output of `ls`](http://mywiki.wooledge.org/ParsingLs) – Charles Duffy Sep 04 '18 at 21:33