Change Names of Multiple Files Linux - linux

I have a number of files with names a1.txt, b1.txt, c1,txt...on ubuntu machine.
Is there any quick way to change all file names to a2.txt, b2.txt, c2.txt...?
In particular, I'd like to replace part of the name string. For instance, every file name contains a string called "apple" and I want to replace "apple" with "pear" in all file names.
Any command or script?

without any extra software you can:
for FILE in *1.txt; do mv "$FILE" $(echo "$FILE" | sed 's/1/2/'); done

for f in {a..c}1.txt; do echo "$f" "${f/1/2}"; done
replace 'echo' with 'mv' if the output looks correct.
and I want to replace "apple" with "linux"
for f in *apple*; do mv "$f" "${f/apple/linux}"; done
The curly brackets in line 1 should work with bash at least.

The following command will rename the specified files by replacing the first occurrence of 1 in their name by 2:
rename 1 2 *1.txt

ls *1.txt | perl -ne 'chomp; $x = $_; $x =~ s/1/2/; rename $_, $x;'

Here's another option that worked for me (following the examples above) for files in different subdirectories
for FILE in $(find . -name *1.txt); do mv "$FILE" "${FILE/1/2}"; done;

Something like this should work:
for i in *1.txt; do
name=$(echo $i | cut -b1)
mv $i ${name}2.txt
done
Modify to suit your needs.

Related

Rename file by swaping text

I need to rename files by swaping some text.
I had for example :
CATEGORIE_2017.pdf
CLASSEMENT_2016.pdf
CATEGORIE_2018.pdf
PROPRETE_2015.pdf
...
and I want them
2017_CATEGORIE.pdf
2016_CLASSEMENT.pdf
2018_CATEGORIE.pdf
2015_PROPRETE.pdf
I came up with this bash version :
ls *.pdf | while read i
do
new_name=$(echo $i |sed -e 's/\(.*\)_\(.*\)\.pdf/\2_\1\.pdf/')
mv $i $new_name
echo "---"
done
It is efficient but seems quite clumsy to me. Does anyone have a smarter solution, for example with rename ?
Using rename you can do the renaming like this:
rename -n 's/([^_]+)_([^.]+).pdf/$2_$1.pdf/g' *.pdf
The option -n does nothing, it just prints what would happen. If you are satisfied, remove the -n option.
I use [^_]+ and [^.]+ to capture the part of the filename before and after the the _. The syntax [^_] means everything but a _.
One way:
ls *.pdf | awk -F"[_.]" '{print "mv "$0" "$2"_"$1"."$3}' | sh
Using awk, swap the positions and form the mv command and pass it to shell.
Using only bash:
for file in *_*.pdf; do
no_ext=${file%.*}
new_name=${no_ext##*_}_${no_ext%_*}.${file##*.}
mv -- "$file" "$new_name"
done

Modify file name using Python Script

I have many files in my folder with names 1.jpg-xyz, 1.jpg-abc, 2.jpg-qwe etc. I particularly want to move .jpg to the end of each image's name. I can't do it manually since these are thousands in number. I can't get rid of xyz etc after .jpg in the current name since they have important information. So only option I have is to shift .jpg to end. Can somebody tell me what command or script should I use to do that?
This should work:
find *jpg* | while read f ; do g=$(echo "$f" | sed s/\.jpg//) ; echo "mv $f ${g}.jpg" ; done
If the mv commands echoed look like what you want then remove the echo "" around it and re-run.
The below bash code will list all files with .jpg- and move them to -.jpg
re='([^.]+)\.jpg(-.*)'
for file in *.jpg-*
do
if [[ $file =~ $re ]]
then
mv $file "${BASH_REMATCH[1]}${BASH_REMATCH[2]}.jpg"
fi
done

Rename part of file name based on exact match in contents of another file

I would like to rename a bunch of files by changing only one part of the file name and doing that based on an exact match in a list in another file. For example, if I have these file names:
sample_ACGTA.txt
sample_ACGTA.fq.abc
sample_ACGT.txt
sample_TTTTTC.tsv
sample_ACCCGGG.fq
sample_ACCCGGG.txt
otherfile.txt
and I want to find and replace based on these exact matches, which are found in another file called replacements.txt:
ACGT name1
TTTTTC longername12
ACCCGGG nam7
ACGTA another4
So that the desired resulting file names would be
sample_another4.txt
sample_another4.fq.abc
sample_name1.txt
sample_longername12.tsv
sample_nam7.fq
sample_nam7.txt
otherfile.txt
I do not want to change the contents. So far I have tried sed and mv based on my search results on this website. With sed I found out how to replace the contents of the file using my list:
while read from to; do
sed -i "s/$from/$to/" infile ;
done < replacements.txt,
and with mv I have found a way to rename files if there is one simple replacement:
for files in sample_*; do
mv "$files" "${files/ACGTA/another4}"
done
But how can I put them together to do what I would like?
Thank you for your help!
You can perfectly combine your for and while loops to only use mv:
while read from to ; do
for i in test* ; do
if [ "$i" != "${i/$from/$to}" ] ; then
mv $i ${i/$from/$to}
fi
done
done < replacements.txt
An alternative solution with sed could consist in using the e command that executes the result of a substitution (Use with caution! Try without the ending e first to print what commands would be executed).
Hence:
sed 's/\(\w\+\)\s\+\(\w\+\)/mv sample_\1\.txt sample_\2\.txt/e' replacements.txt
would parse your replacements.txt file and rename all your .txt files as desired.
We just have to add a loop to deal with the other extentions:
for j in .txt .bak .tsv .fq .fq.abc ; do
sed "s/\(\w\+\)\s\+\(\w\+\)/mv 'sample_\1$j' 'sample_\2$j'/e" replacements.txt
done
(Note that you should get error messages when it tries to rename non-existing files, for example when it tries to execute mv sample_ACGT.fq sample_name1.fq but file sample_ACGT.fq does not exist)
You could use awk to generate commands:
% awk '{print "for files in sample_*; do mv $files ${files/" $1 "/" $2 "}; done" }' replacements.txt
for files in sample_*; do mv $files ${files/ACGT/name1}; done
for files in sample_*; do mv $files ${files/TTTTTC/longername12}; done
for files in sample_*; do mv $files ${files/ACCCGGG/nam7}; done
for files in sample_*; do mv $files ${files/ACGTA/another4}; done
Then either copy/paste or pipe the output directly to your shell:
% awk '{print "for files in sample_*; do mv $files ${files/" $1 "/" $2 "}; done" }' replacements.txt | bash
If you want the longer match string to be used first, sort the replacements first:
% sort -r replacements.txt | awk '{print "for files in sample_*; do mv $files ${files/" $1 "/" $2 "}; done" }' | bash

batch rename files in ubuntu

I am in need of some command line fu.
I have a wack of files, starting with 4 numbers then a dash then various letters then extentsion, eg.
0851_blahblah_p.dbf
0754_asdf_l.dbf
What I want is to move the four numbers to the end of the filename (keeping the extension in tact) and remove the underscore. Thus the above example would be renamed:
blahblah_p0851.dbf
asdf_l0754.dbf
All help is appreciated.
I am running ubuntu.
Thanks DJ
Here is a solution in pure bash:
for file in *.dbf; do
ext=${file##*.};num=${file%%_*};name=${file%.*};name=${name#*_}
mv $file $name$num"."$ext;
done
Broken down with comments:
for file in *.dbf
do
ext=${file##*.} # Capture the extension
num=${file%%_*} # Capture the number
name=${file%.*} # Step 1: Capture the name
name=${name#*_} # Step 2: Capture the name
mv "$file" "$name$num.$ext" # move the files to new name
done
You can use the rename command:
rename 's/([0-9]{4})_([[:alpha:]]*)_.*.dbf/$2_$1.dbf/' *
You can use sed also
$sed -r 's/([^_]+)_([^.]+)/\2\1/g'
Using this way the given name is splitted and modified as per your requirement.
(or)
Use this script and pass the file names as argument it will move the file name as per the requirement.
#!/bin/sh
if [ $# -ne 1 ] ; then
echo "Usage : <sh filename> <arguments>"
exit ;
fi
for file in $*
do
mv $file `echo $file | sed -r 's/([^_]+)_([^.]+)/\2\1/g' `
done

Removing 10 Characters of Filename in Linux

I just downloaded about 600 files from my server and need to remove the last 11 characters from the filename (not including the extension). I use Ubuntu and I am searching for a command to achieve this.
Some examples are as follows:
aarondyne_kh2_13thstruggle_or_1250556383.mus should be renamed to aarondyne_kh2_13thstruggle_or.mus
aarondyne_kh2_darknessofunknow_1250556659.mp3 should be renamed to aarondyne_kh2_darknessofunknow.mp3
It seems that some duplicates might exist after I do this, but if the command fails to complete and tells me what the duplicates would be, I can always remove those manually.
Try using the rename command. It allows you to rename files based on a regular expression:
The following line should work out for you:
rename 's/_\d+(\.[a-z0-9A-Z]+)$/$1/' *
The following changes will occur:
aarondyne_kh2_13thstruggle_or_1250556383.mus renamed as aarondyne_kh2_13thstruggle_or.mus
aarondyne_kh2_darknessofunknow_1250556659.mp3 renamed as aarondyne_kh2_darknessofunknow.mp3
You can check the actions rename will do via specifying the -n flag, like this:
rename -n 's/_\d+(\.[a-z0-9A-Z]+)$/$1/' *
For more information on how to use rename simply open the manpage via: man rename
Not the prettiest, but very simple:
echo "$filename" | sed -e 's!\(.*\)...........\(\.[^.]*\)!\1\2!'
You'll still need to write the rest of the script, but it's pretty simple.
find . -type f -exec sh -c 'mv {} `echo -n {} | sed -E -e "s/[^/]{10}(\\.[^\\.]+)?$/\\1/"`' ";"
one way to go:
you get a list of your files, one per line (by ls maybe) then:
ls....|awk '{o=$0;sub(/_[^_.]*\./,".",$0);print "mv "o" "$0}'
this will print the mv a b command
e.g.
kent$ echo "aarondyne_kh2_13thstruggle_or_1250556383.mus"|awk '{o=$0;sub(/_[^_.]*\./,".",$0);print "mv "o" "$0}'
mv aarondyne_kh2_13thstruggle_or_1250556383.mus aarondyne_kh2_13thstruggle_or.mus
to execute, just pipe it to |sh
I assume there is no space in your filename.
This script assumes each file has just one extension. It would, for instance, rename "foo.something.mus" to "foo.mus". To keep all extensions, remove one hash mark (#) from the first line of the loop body. It also assumes that the base of each filename has at least 12 character, so that removing 11 doesn't leave you with an empty name.
for f in *; do
ext=${f##*.}
new_f=${base%???????????.$ext}
if [ -f "$new_f" ]; then
echo "Will not rename $f, $new_f already exists" >&2
else
mv "$f" "$new_f"
fi
done

Resources