73

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".

5 Answers 5

113

Bash can do sed-like substitutions:

for file in *; do mv "${file}" "${file/000/}"; done
Sign up to request clarification or add additional context in comments.

8 Comments

Nice, can you explain the function of "{" ?
For documentation on this functionality please see section 3.5.3 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 from Advanced Bash-Scripting Guide.
@irnc: Another: Parameter Expansion
Best answer, IMO.
@hrdom: You will need to use special quoting in order to have the newline escape interpreted: for file in *; do mv "${file}" "${file/$'\n/'}"; done . And if your filenames might have more than one newline and you want to remove all of them then double the first slash: for file in *; do mv "${file}" "${file//$'\n/'}"; done
|
86

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.

3 Comments

+1 for most portable solution (and because I'm running too low on upvotes to keep upvoting all the good answers).
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, and running a separate copy of sed for each name is very slow)
...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.
15

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

Comments

5

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

Comments

3

Piping the output of ls is widely considered to be very dangerous because it's not predictable or portable, but if you are willing to take the risk:

#!/bin/bash
ls | while read name; do
  echo mv $name ${name/$1//}
done

4 Comments

@Laurence Gonsalves: using shell wildcards expand the command line, and there's a not-so big limit there. "while read" avoids that
@Laurence: This is also much more extensible. It's commonly used with find on the front.
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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.