I am trying to use sed
to rename all .txt
files in /home/cmccabe/test
. However, I am getting an error that I seems to be putting the files in a new directory s, instead of in the original. Thank you :).
bash
# rename classified
cd /home/cmccabe/test
pattern2_old="_classify"
pattern2_new="hg19multianno"
for file in *.txt
do
newname=`printf '%s\n' "$file" | /bin/sed -e "s/$pattern2_old/$pattern2_new//"`
/bin/mv -fv "$file" "$newname"
done
/bin/sed: -e expression #1, char 27: unknown option to `s'
�17-0000_classify.txt� -> ��
/bin/mv: cannot move �17-0000_classify.txt� to ��: No such file or directory
/bin/sed: -e expression #1, char 27: unknown option to `s'
�17-0001_classify.txt� -> ��
/bin/mv: cannot move �17-0001_classify.txt� to ��: No such file or directory
contents of /home/cmccabe/test
before script executed
17-0000_classify.txt
17-0001_classify.txt
17-0002_classify.txt
contents of /home/cmccabe/test
after script executed (desired output)
17-0000_hg19multiannotxt
17-0001_hg19multianno.txt
17-0002_hg19multianno.txt
You get the error because this:
sed -e "s/$pattern2_old/$pattern2_new//"
is not a valid sed
-command. The s-subcommand has the form:
s/<regexp>/<regexp>/
and the last slash at the end leads to a simple syntax error.
Furthermore, your script is about as badly written as can be:
cd /home/cmccabe/test
Never do that in a script. Ideally you should use a commandline argument to provide the directory in question, but in absence of this do it this way:
dir="/home/cmccabe/test"
for file in "$dir"/* ; do
mv $file ....
done
Secondly:
for file in *.txt
do
newname=`printf '%s\n' "$file" | /bin/sed -e "s/$pattern2_old/$pattern2_new//"`
/bin/mv -fv "$file" "$newname"
done
I spare you the obligatory sermon about not using backticks: you have been told this perhaps several dozen times already and i find the insistence to write bad scripts commendable. The POSIX variant of $(...)
has only been developed to have something one can safely ignore.
You still may consider to invoke sed only once per run of the script instead of once per file the script encounters:
old="classify"
new="hg19multianno"
ls -1 "$dir"/*.txt |\
sed 's/\(.*\)'"$old"'\(.*\)/\1'"$old"'\2 \1'"$new"'\2/' |\
while read oldfile newfile ; do
mv "$oldfile" "$newfile"
done
But even this is just a waste of processing power and other resources, because you can do the same with variable expansion inside the shell, without any external program:
old="classify"
new="hg19multianno"
ls -1 "$dir"/*txt |\
while read file ; do
mv "$file" "${file/${old}/${new}}"
done
I hope this helps.
bakunin
1 Like
Thank you very much for your help and explanations :).