I need a scrip to replace .png with #2x.png How can I do this for all file names in a directory?
Assuming bash:
for f in *.png; do
mv "$f" "${f%.png}#2x.png"
done
Explanation:
Line 1:
for f in *.png; do
For loop. Iterates over all filenames in the current directory that match the glob pattern *.png, sets $f to each name in turn, and executes the body of the loop.
Line 2:
mv "$f" "${f%.png}#2x.png"
Executes the mv tool. The first arg is just "$f", which is the file you want to rename. The second arg is a two-step process:
${f%.png} evaluates to the filename with the extension .png stripped off.
Following the stripped filename is #2x.png, which just appends that string back onto the filename.
Line 3:
done
Terminates the for loop.
The following script should work for you:
#!/bin/bash
for file in *.png
do
filename=$(basename "$file")
filename="${filename%.*}"
filename="${filename}#2x.png"
mv "$file" "$filename"
done
Related
I totally understand what the problem is here.
I have a set of files, prepended as 'cat.jpg' and 'dog.jpg.' I just want to move the 'cat.jpg' files into a directory called 'cat.' Same with the 'dog.jpg' files.
for f in *.jpg; do
name=`echo "$f"|sed 's/ -.*//'`
firstThreeLetters=`echo "$name"|cut -c 1-3`
dir="path/$firstThreeLetters"
mv "$f" "$dir"
done
I get this message:
mv: cannot stat '*.jpg': No such file or directory
That's fine. But I can't find any way to iterate over these images without using that wildcard.
I don't want to use the wildcard. The only files are prepended with the 'dog' or 'cat'. I don't need to match. All the files are .jpgs.
Can't I just iterate over the contents of the directory without using a wildcard? I know this is a bit of an XY Problem but still I would like to learn this.
*.jpg would yield the literal *.jpg when there are no matching files.
Looks like you need nullglob. With Bash, you can do this:
#!/bin/bash
shopt -s nullglob # makes glob expand to nothing in case there are no matching files
for f in cat*.jpg dog*.jpg; do # pick only cat & dog files
first3=${f:0:3} # grab first 3 characters of filename
[[ -d "$first3" ]] || continue # skip if there is no such dir
mv "$f" "$first3/$f" # move
done
I am trying to use bash to rename all .txt files in a directory that match a specific pattern. My two attempts below have removed the files from the directory and threw an error. Thank you :)
input
16-0000_File-A_variant_strandbias_readcount.vcf.hg19_multianno_dbremoved_removed_final_index_inheritence_import.txt
16-0002_File-B_variant_strandbias_readcount.vcf.hg19_multianno_dbremoved_removed_final_index_inheritence_import.txt
desired output
16-0000_File-A_multianno.txt
16-0002_File-B_multianno.txt
Bash attempt 1 this removes the files from the directory
for f in /home/cmccabe/Desktop/test/vcf/overall/annovar/*_classify.txt ; do
# Grab file prefix.
p=${f%%_*_}
bname=`basename $f`
pref=${bname%%.txt}
mv "$f" ${p}_multianno.txt
done
Bash attempt 2 Substitution replacement not terminated at (eval 1) line 1.
for f in /home/cmccabe/Desktop/test/vcf/overall/annovar/*_classify.txt ; do
# Grab file prefix.
p=${f%%_*_}
bname=`basename $f`
pref=${bname%%.txt}
rename -n 's/^$f/' *${p}_multianno.txt
done
You don't need a loop. rename alone can do this:
rename -n 's/(.*?_[^_]+).*/${1}_multianno.txt/g' /home/cmccabe/Desktop/test/vcf/overall/annovar/*_classify.txt
The meaning of the regular expression is roughly,
capture everything from the start until the 2nd _,
match the rest,
and replace with the captured prefix and append _multianno.txt
With the -n flag, this command will print what it would do without actually doing it.
When the output looks good, remove the -n and rerun.
I have got a directory with files in which some of then end with an underscore.
I would like to test each file to see if it ends with an underscore and then strip off the underscore.
I am currently running the following code:
for file in *;do
echo $file;
if [[ "${file:$length:1}" == "_" ]];then
mv $file $(echo $file | sed "s/.$//g");
fi
done
But it does not seem to be renaming the files with underscore. For example if i have a file called all_indoors_ I expect it to give me all_indoors.
You could use built-in string substitution:
for file in *_; do
mv "$file" "${file%_}"
done
Just use a regex to check the string:
for file in *
do
[[ $file =~ "_$" ]] && echo mv "$file" "${file%%_}"
done
Once you are sure it works as intended, remove the echo so that the mv command executes!
It may even be cleaner to use *_ so that the for will just loop over the files with a name ending with _, as hek2mgl suggests in comments.
for file in *_
do
echo mv "$file" "${file%%_}"
done
You can use which will be recursive:
while read f; do
mv "$f" "${f:0:-1}"; # Remove last character from $f
done < <(find . -type f -name '*_')
Although not a pure bash approach, you can use rename.ul (written by Larry Wall, the person behind perl). Rename is not part of the default linux environment, but is part of util-linux.
You use rename with:
rename perlexpr files
(some flags ommitted).
So you could use:
rename 's/_$//' *
if you want to remove all characters including and after the underscore.
As #hek2mgl points out, there are multiple rename commands (see here), so first test if you have picked the right one.
On OSX 10.8, how can I rename all files in the current directory by removing certain amount of character from the of the name? Example:
my_img_1#2x.png to become my_img_1.png
So only #2x part will be removed.
The exact way to do this depends on your files - for example, are they all PNG files? Do you want to remove #2x from all of them? Here is a loop which will remove the 3 characters before the file extension from all files in the current directory:
for f in *; do
echo mv "$f" $(sed -r 's/(.*).{3}\.([^\.]+)/\1.\2/' <<< "$f")
done
If all your files are named [something]#2x.png and you want them to be renamed [something].png, this will work:
for f in *; do
echo mv "$f" "${f%#*}.png"
done
This works using parameter expansion - effectively the construct ${var%pattern} means "take $var and remove the shortest string that matches [pattern] from the end of it". So in this case, ${f%#*} means "remove the last # and anything after it from $f". Then we append .png to replace the file extension which has been removed as part of that operation.
$f = filename#2x.png
${f%#*} = filename
${f%#*}.png = filename.png
I need to rename 45 files, and I don't want to do it one by one. These are the file names:
chr10.fasta chr13_random.fasta chr17.fasta chr1.fasta chr22_random.fasta chr4_random.fasta chr7_random.fasta chrX.fasta
chr10_random.fasta chr14.fasta chr17_random.fasta chr1_random.fasta chr2.fasta chr5.fasta chr8.fasta chrX_random.fasta
chr11.fasta chr15.fasta chr18.fasta chr20.fasta chr2_random.fasta chr5_random.fasta chr8_random.fasta chrY.fasta
chr11_random.fasta chr15_random.fasta chr18_random.fasta chr21.fasta chr3.fasta chr6.fasta chr9.fasta
chr12.fasta chr16.fasta chr19.fasta chr21_random.fasta chr3_random.fasta chr6_random.fasta chr9_random.fasta
chr13.fasta chr16_random.fasta chr19_random.fasta chr22.fasta chr4.fasta chr7.fasta chrM.fasta
I need to change the extension ".fasta" to ".fa". I'm trying to write a bash script to do it:
for i in $(ls chr*)
do
NEWNAME = `echo $i | sed 's/sta//g'`
mv $i $NEWNAME
done
But it doesn't work. Can you tell me why, or give another quick solution?
Thanks!
Several mistakes here:
NEWNAME = should be without space. Here bash is looking for a command named NEWNAME and that fails.
you parse the output of ls. this is bad if you had files with spaces. Bash can build itself a list of files with the glob operator *.
You don't escape "$i" and "$NEWNAME". If any of them contains a space it makes two arguments for mv.
If a file name begins with a dash mv will believe it is a switch. Use -- to stop argument processing.
Try:
for i in chr*
do
mv -- "$i" "${i/%.fasta/.fa}"
done
or
for i in chr*
do
NEWNAME="${i/%.fasta/.fa}"
mv -- "$i" "$NEWNAME"
done
The "%{var/%pat/replacement}" looks for pat only at the end of the variable and replaces it with replacement.
for f in chr*.fasta; do mv "$f" "${f/%.fasta/.fa}"; done
If you have the rename command, you can do:
rename .fasta .fa chr*.fasta