Dead simple.
How do I rename
05_h.png
06_h.png
to
05_half.png
06_half.png
At least, I think it's simple, but it's hard to Google for this kind of thing unless you already know.
Thanks....
Just use bash, no need to call external commands.
for file in *_h.png
do
mv "$file" "${file/_h.png/_half.png}"
done
Do not add #!/bin/sh
For those that need that one-liner:
for file in *.png; do mv "$file" "${file/_h.png/_half.png}"; done
Try rename command:
rename 's/_h.png/_half.png/' *.png
Update:
example usage:
create some content
$ mkdir /tmp/foo
$ cd /tmp/foo
$ touch one_h.png two_h.png three_h.png
$ ls
one_h.png three_h.png two_h.png
test solution:
$ rename 's/_h.png/_half.png/' *.png
$ ls
one_half.png three_half.png two_half.png
for f in *.png; do
fnew=`echo $f | sed 's/_h.png/_half.png/'`
mv $f $fnew
done
Or in one-liner:
for f in *.png; do mv "$f" "$(echo $f | sed 's/_h.png$/_half.png/g')"; done
Are you looking for a pure bash solution? There are many approaches, but here's one.
for file in *_h.png ; do mv "$file" "${file%%_h.png}_half.png" ; done
This presumes that the only files in the current directory that end in _h.png are the ones you want to rename.
Much more specifically
for file in 0{5..6}_h.png ; do mv "$file" "${file/_h./_half.}" ; done
Presuming those two examples are your only. files.
For the general case, file renaming in has
been covered
before.
Use the rename utility written in perl.
Might be that it is not available by default though...
$ touch 0{5..6}_h.png
$ ls
05_h.png 06_h.png
$ rename 's/h/half/' *.png
$ ls
05_half.png 06_half.png
for i in *_h.png ; do
mv $i `echo "$i"|awk -F'.' '{print $1"alf."$2}'`
done
I had a similar question:
In the manual, it describes rename as
rename [option] expression replacement file
so you can use it in this way
rename _h _half *.png
In the code:
'_h' is the expression that you are looking for.
'_half' is the pattern that you want to replace with.
'*.png' is the range of files that you are looking for your possible target files.
Hope this can help c:
Another approach can be manually using batch rename option
Right click on the file -> File Custom Commands -> Batch Rename
and you can replace h. with half.
This will work for linux based gui using WinSCP etc
One liner:
for file in *.php ; do mv "$file" "_$file" ; done
Although the answer set is complete, I need to add another missing one.
for i in *_h.png;
do name=`echo "$i" | cut -d'_' -f1`
echo "Executing of name $name"
mv "$i" "${name}_half.png"
done
I had to rename the prefix of files and I found this answer with a solution like this:
for i in h_*; do mv ${i/#h_/half_}; done
If pattern begins with #, it must match at the beginning of the
expanded value of parameter. If pattern begins with %, it must match
at the end of the expanded value of parameter.
from man bash
Use the rename utility:
rc#bvm3:/tmp/foo $ touch 05_h.png 06_h.png
rc#bvm3:/tmp/foo $ rename 's/_h/_half/' *
rc#bvm3:/tmp/foo $ ls -l
total 0
-rw-r--r-- 1 rc rc 0 2011-09-17 00:15 05_half.png
-rw-r--r-- 1 rc rc 0 2011-09-17 00:15 06_half.png
Related
i have found this command to replace spaces with underscores:
for file in *.jpg; do mv "$file" ${file// /_}; done
but many pics have chars like ' # ñ and want to remove those automatically and also wanted to add a suffix o prefix.
ex.
pic's#nick_0001.jpg
pic's#nick_0003.jpg
pic's#nick_0003.jpg
to
vacations_pics_nick_0001.jpg
pics_nick_0001_vacations.jpg
can you help me?
for file in *.jpg
do
mv "$file" $(sed 's/[^ [:alnum:]]//g;s/ /_/g;s/^/your_prefix/' <<<"$file")
done
Should do the job
both solution works fine.
is there a way to use that command on a single line, like the example i give to use with others comand together:
for file in * do mv "$file" "${file//[^a-z0-9]/_}" done;
??'
Using bash:
for file in *
do
mv "$file" "${file//[^a-z0-9]/_}"
done
Test:
$ touch "pic's#nick_0001.jpg"
$ ls
pic's#nick_0001.jpg
$ for file in *; do mv "$file" "${file//[^a-z0-9]/_}"; done
$ ls
pic_s_nick_0001_jpg
I have a bunch of files which are copied by "mv --backup=t source destination". So these files are in format *.*.~[0-9]~
For example,
some_file_name.pdf.~1~
some_file_name.pdf.~2~
another_file_name.docx.~1~
another_file_name.docx.~2~
Now, I would like to rename all such files so that the backup extension number came before the actual extension. Like
some_file_name_1.pdf
some_file_name_2.pdf
another_file_name_1.docx
another_file_name_2.docx
Is there a way to do in Unix using shell?
Any thoughts would be appreciated. Thank you in advance.
Using BASH regex directives you can do this:
for f in *~; do
[[ $f =~ ^(.+)\.([^.]+)\.~([0-9]+)~$ ]] &&
echo mv "$f" "${BASH_REMATCH[1]}_${BASH_REMATCH[3]}.${BASH_REMATCH[2]}"
done
Output:
mv CR_71050_5.3.17.pdf.~1~ CR_71050_5.3.17_1.pdf
mv another_file_name.docx.~1~ another_file_name_1.docx
mv another_file_name.docx.~2~ another_file_name_2.docx
mv some_file_name.pdf.~1~ some_file_name_1.pdf
mv some_file_name.pdf.~2~ some_file_name_2.pdf
Once you're satisfied, you can remove echo before mv
Try:
awk -F~ '{ split($1,splt,".");system("mv "$0" "splt[1]"_"$2"."splt[2]) }'
We are essentially splitting the filenames on ~ and then using awks split function to further split the text and then pass it to the system function to execute the mv command.
You can use rename (it is available as a Debian package).
$ ls
file.pdf.~1~ file.pdf.~10~ file.pdf.~2~ file.pdf.~3~ file.pdf.~9~
$ rename 's/.pdf.~([0-9]+)~$/$1.pdf/' *.pdf.~*~
$ ls
file10.pdf file1.pdf file2.pdf file3.pdf file9.pdf
I'm fairly new to bash so sorry if this is kind of a basic question. I was trying to rename a bunch of mp3 files to prepend 1- to their filenames, and mv *.mp3 1-*.mp3 didn't work unfortunately. So I tried to script it, first with echo to test the commands:
for f in *.mp3 ; do echo mv \'$f\' \'1-$f\'; done
Which seems to output the commands that I like, so I removed the echo, changing the command to
for f in *.mp3 ; do mv \'$f\' \'1-$f\'; done
Which failed. Next I tried piping the commands onward like so
for f in *.mp3 ; do echo mv \'$f\' \'1-$f\'; done | /bin/sh
Which worked, but if anyone could enlighten me as to why the middle command doesn't work I would be interested to know. Or if there is an more elegant one-liner that would do what I wanted, I would be interested to see that too.
I think you have to change the command to
for f in *.mp3 ; do mv "$f" "1-$f"; done
Otherwise you would pass something like 'file1.mp3' and '1-file1.mp3' to mv (including the single quotes).
Dry run:
rename -n 's/^/1-/' *.mp3
Remove the -n if it looks correct to run the command. man rename for details.
I have a folder with files named as
input (1).txt
input (2).txt
input (3).txt
...
input (207).txt
How do I rename them to
input_1.in
input_2.in
input_3.in
...
input_207.in
I am trying this
for f in *.txt ; do mv $f `echo $f | sed -e 's/input\ (\(\d*\))\.txt/input_\1.in/'` ; done
But it gives me
mv: target `(100).txt' is not a directory
mv: target `(101).txt' is not a directory
mv: target `(102).txt' is not a directory
...
Where did I go wrong?
I have put in the quotes now, but I get this now
mv: `input (90).txt' and `input (90).txt' are the same file
It is somehow trying to rename the file to the same name. How is that happening?
That is because bash for split the element with space ' ' so you are commanding it to move 'input' to '(1)'.
The way to solve this is to tell bash to split by new line using IFS variable.
Like this:
IFS=$'\n'
Then do your command.
However, I suggest you to use find to do this instead using -exec command.
For example:
find *.txt -exec mv "{}" `echo "{}" | sed -e 's/input\ (\([0-9]*\))\.txt/input_\1.in/'` \;
NOTE: I write this from memory and I did test this so let try and adjust it.
Hope this helps.
You're forgetting to quote your arguments.
... mv "$f" "$(echo "$f" | ... )" ; done
no need to call external commands
#!/bin/bash
shopt -s nullglob
shopt -s extglob
for file in *.txt
do
newfile="${file//[)]/}"
newfile="${file// [(]/_}"
mv "$file" "${newfile%.txt}.in"
done
As you've already fixed, you need to quote the $f argument to mv.
As to your second problem, sed doesn't support \d. You could use [0-9] instead.
for f in *.txt ; do mv "$f" `echo $f | sed -e 's/input\ (\(\d*\))\.txt/input_\1.in/'` ; done
If you have GNU Parallel http://www.gnu.org/software/parallel/ installed you can do this:
seq 1 207 | parallel -q mv 'input ({}).txt' input_{}.in
Watch the intro video for GNU Parallel to learn more:
http://www.youtube.com/watch?v=OpaiGYxkSuQ
I have a directory with a bunch of files with names like:
001234.jpg
001235.jpg
004729342.jpg
I want to remove the leading zeros from all file names, so I'd be left with:
1234.jpg
1235.jpg
4729342.jpg
I've been trying different configurations of sed, but I can't find the proper syntax. Is there an easy way to list all files in the directory, pipe it through sed, and either move or copy them to the new file name without the leading zeros?
for FILE in `ls`; do mv $FILE `echo $FILE | sed -e 's:^0*::'`; done
sed by itself is the wrong tool for this: you need to use some shell scripting as well.
Check Rename multiple files with Linux page for some ideas. One of the ideas suggested is to use the rename perl script:
rename 's/^0*//' *.jpg
In Bash, which is likely to be your default login shell, no external commands are necessary.
shopt -s extglob
for i in 0*[^0]; do mv "$i" "${i##*(0)}"; done
Maybe not the most elegant but it will work.
for i in 0*
do
mv "${i}" "`expr "${i}" : '0*\(.*\)'`"
done
Try using sed, e.g.:
sed -e 's:^0*::'
Complete loop:
for f in `ls`; do
mv $f $(echo $f | sed -e 's:^0*::')
done
I dont know sed at all but you can get a listing by using find:
find -type f -name *.jpg
so with the other answer it might look like
find . -type f -name *.jpg | sed -e 's:^0*::'
but i dont know if that sed command holds up or not.
Here's one that doesn't require sed:
for x in *.jpg ; do let num="10#${x%%.jpg}"; mv $x ${num}.jpg ; done
Note that this ONLY works when the filenames are all numbers. You could also remove the leading zeros using the shell:
for a in *.jpg ; do dest=${a/*(0)/} ; mv $a $dest ; done
In Bash shell you can do:
shopt -s nullglob
for file in 0*.jpg
do
echo mv "$file" "${file##*0}"
done