Cut sub-string and rename files use shell command [duplicate] - shell

This question already has answers here:
How to rename with prefix/suffix?
(10 answers)
Closed 7 years ago.
How to rename file names? I want to map names:
abc-hdpi.png ⟶ abc.png
bcd-hdpi.png ⟶ bcd.png
...
I have many files to do this, so mv abc-hdpi.png abc.png is not a good solution.

Search for prename (Perl rename) command; it can do the job easily:
prename 's/-hdpi.png/.png/' *-hdpi.png
Failing that:
for file in *-hdpi.png
do
mv "$file" "${file%-hdpi.png}.png"
done

You can extract from a fixed length string like so:
NAME[0]="abc-hdpi.png"
NAME[1]="def-hdpi.png"
NAME[2]="ghi-hdpi.png"
NAME[3]="jkl-hdpi.png"
NAME[4]="mno-hdpi.png"
rename(){
var=$1
mv $var $var{0:2}$var{8:}
}
for i in "${Name[#]}"
do
rename $i
done

Related

Can bash be used to rename by pattern? [duplicate]

This question already has answers here:
Rename files using regular expression in linux
(10 answers)
Closed 2 years ago.
I have files:
alpha_123_abc_file.txt
beta_456_def_file.txt
gamma_789_ghi_file.txt
Is there a way to rename all to cut the parts after the first _ character? To become:
123_abc_file.txt
456_def_file.txt
789_ghi_file.txt
I've looked into the perl tool but I an unsure if it has the capability to search out a pattern like that.
for file in *_*; do echo mv -- "$file" "${file#*_}"; done
Remove the echo when you're done testing and ready to actually do the mv.

Bash for loop and glob expansion [duplicate]

This question already has answers here:
Looping on empty directory content in Bash [duplicate]
(2 answers)
Closed 7 years ago.
Consider the following bash code:
for f in /tmp/*.dat; do echo ${f}; done
when I run this and there is no *.dat file in /tmp the output is:
/tmp/*.dat
which is clearly not what I want. However, when there is such a file, it will print out the correct one
/tmp/foo.dat
How can I force the for loop to return 'nothing' when there is no such file in the directory. The find-command is not an option, sorry for that :/ I would like to have also a solution without testing, if *.dat is a file or not. Any solutions so far?
This should work:
shopt -s nullglob
...
From Bash Manual
nullglob
If set, Bash allows filename patterns which match no files to expand
to a null string, rather than themselves.

bash script rename multiple files [duplicate]

This question already has answers here:
Rename filename to another name
(3 answers)
Closed 7 years ago.
Let´s say I have a bunch of files named something like this: bsdsa120226.nai bdeqa140223.nai and I want to rename them to 120226.nai 140223.nai. How can i achieve this using the script below?
#!/bin/bash
name1=`ls *nai*`
names=`ls *nai*| grep -Po '(?<=.{5}).+'`
for i in $name1
do
for y in $names
do
mv $i $y
done
done
Solution:
name1=`ls *nai*`
for i in $name1
do
y=$(echo "$i" | grep -Po '(?<=.{5}).+')
mv $i $y
done
This:
#!/bin/bash
shopt -s extglob nullglob
for file in *+([[:digit:]]).nai; do
echo mv -nv -- "$file" "${file##+([^[:digit:]])}"
done
Remove the echo if you're happy with the mv commands.
Note. This solution does not assume that there are 5 leading characters to delete. It will delete all the leading non-numeric characters.
Using only bash, you could do this:
for file in *nai* ; do
echo mv -- "$file" "${file:5}"
done
(Remove the echo when satisfied with the output.)
Avoid ls in scripts, except for displaying information. Use plain globbing instead.
See also How do I do string manipulations in bash? for more string manipulation techniques.
Your script can't work with that structure: if you have 5 files, it will call mv five times for the first file (once for each element in the second list), five times for the second, etc. You'd need to iterate over the two sets of names in lockstep. (It also doesn't deal with things like whitespace in filenames.)
You would be better off using rename (prename on some systems) since that allows you to use Perl regular expressions to do the renaming, along the lines of:
prename 's/^.{5}//' *.nai
The reason your script is not behaving is that, for every source file, you're attempting to rename it to every target file.
If you need to limit yourself to using that script, you need to work out the single target file for each source file, something like:
#!/bin/bash
for i in *.nai; do
y=$(echo "$i" | cut -c6-)
mv "$i" "$y"
done
If your system has rename tool, it's better to go with the simple rename command,
rename 's/^.{5}//' *.nai
It just remove the first 5 characters from the file name.
OR
for i in *.nai; do mv "$i" $(grep -oP '(?<=^.{5}).+' <<< "$i"); done

Bash loop for multiple files [duplicate]

This question already has answers here:
Bash input for multiple file
(5 answers)
Closed 8 years ago.
I have thousands of two set of files, one with name.ext and another set for the same name ending with name.new.psl. So for every name.ext there is a name.new.psl. Now I have to pass this as arguments to a script such as customise.pl name.ext name.new.psl
Any ideas for a loop in bash? The first name is common for each name.ext and name.new.psl like:
perl customise.pl name.ext name.new.psl
for f in *.ext ; do
perl customise.pl "${f}" "${f/%.txt/.new.psl}"
done
Will do it for you in the current working directory.
for fname in *.ext
do
perl customise.pl "$fname" "${fname%.ext}.new.psl"
done
The above does not require any special bash features. So, it is compatible with, for example, dash which is the default shell (/bin/sh) on debian-derived distributions.
The trick above is that ${fname%.ext} tells the shell to remove the text .ext from the end of $fname, leaving just the "name" part. Thus, "${fname%.ext}.new.psl" removes .ext adds the .new.psl extension.
The file names in the code above are in double-quotes. This is so that this script will work even if the file names have spaces in them.
for i in `ls *.ext`; do NAME=`echo $i | awk -F '.' '{print $1}'`; perl customise.pl $NAME.ext $NAME.new.psl; done

rename filenames under a folder, make them shorter [duplicate]

This question already has answers here:
Rename multiple files based on pattern in Unix
(24 answers)
Closed 9 years ago.
I have a folder contains many .ass files for subtitles of a TV show
but the file name is just too long:
House.of.Cards.S01E01.WEBRip.720p.H.264.AAC.2.0-HoC.SOME-OTHER-THINGS.ass
House.of.Cards.S01E02.WEBRip.720p.H.264.AAC.2.0-HoC.SOME-OTHER-THINGS.ass
House.of.Cards.S01E03.WEBRip.720p.H.264.AAC.2.0-HoC.SOME-OTHER-THINGS.ass
now I just want to change them into shorter form:
House.of.Cards.S01E01.ass
House.of.Cards.S01E02.ass
House.of.Cards.S01E03.ass
is there any simple way to do it? (may be via shell script)
Thanks in advance
there is a (not so) simple way to do it
for f in *; do mv "$f" "${f//.H.*/}"; done
for f in *; do mv "$f" "$f.ass"; done

Resources