Rename multiple files while keeping the same extension on Linux - linux

I have 100s of files in a directory with the following naming convention.
00XYZCD042ABCDE20141002ABCDE.XML
00XYZCC011ABCDE20141002.TXT
00XYZCB165ABCDE20141002ABCDE.TXT
00XYZCB165ABCDE20141002ABCDE.CSV
I want to rename these files using bash, awk, cut, sed, so that I get the output:
XYZCD042.XML
XYZCC011.TXT
XYZCB165.TXT
XYZCB165.CSV
So basically, remove the first two 0s always, and then keep everything until ABCDE starts and then remove everything including ABCDE and keep the file extension.

You could try the below rename command,
rename 's/ABCDE.*(\..*)/$1/;s/^00//' *
Explanation:
s/ABCDE.*(\..*)/$1/ Matches all the characters from the first ABCDE upto the last and captures only the extension part. Then all the matched chars are replaced with that captured extension.
s/^00// Then this would remove the leading two zeros.

Bash only:
for fn in *; do
A=${fn#00}
mv $fn ${A/ABCDE*./.}
done
The first line in the for loop strips the 00 prefix, and the second line strips the ABCDE suffix (up to a dot), then performs the rename.

for file in *
do
mv -- "$file" "${file:2:8}.${file#*.}"
done
It's important to always quote your variables unless you have a specific purpose in mind and understand all of the effects.

for i in *; do
mv $i $(echo $i | sed -e 's/^00//' -e 's/ABCDE2014[^.]*//');
done

Related

How do I replace ".net" with space using sed in Linux?

I'm using for loop, with arguments i. Each argument contains ".net" at the end and in directory they are in one line, divided by some space. Now I need to get rid of these ".net" using substitution of sed, but it's not working. I went through different options, the most recent one is
sed 's/\.(net)//g' $i;
which is obviously not correct, but I just can't find anything online about this.
To make it clear, lets say I have a directory with 5 files with names
file1.net
file2.net
file3.net
file4.net
file5.net
I would like my output to be
file1
file2
file3
file
file5
...Could somebody give me some advice?
You can use
for f in *.net; do mv "$f" "${f%.*}"; done
Details:
for f in *.net; - iterates over files with net extension
mv "$f" "${f%.*}" - renames the files with the file without net extension (${f%.*} removes all text - as few as possible - from the end of f till the first ., see Parameter expansion).
This is a work for perl's rename :
rename -n 's/\.net//' *.net
The -n is for test purpose. Remove it if the output looks good for you
This way:
sed -i.backup 's/\.net$//g' "$1";
It will create a backup for safeness

rename all files after extension

Is it possible to write a script to rename all files after the extension?
Example in the folder, there are :
hello.txt-123ahr
bye.txt-56athe
test.txt-98hg12
I want the output:
hello.txt
bye.txt
test.txt
If you just want to remove everything from the dash forwards, you can use Parameter expansion:
#!/bin/bash
for file in *.txt-* ; do
mv "$file" "${file%-*}"
done
Where ${file%-*} means "remove from $file everytning from the last dash". If you want to start from the first dash, use %%.
Note that you might overwrite some files if their leading parts are equivalent, e.g. hello.txt-123abc and hello.txt-456xyz.

How to batch-rename files by date?

What commands could I use to rename a few hundred files that are currently named
file.2003-01-02.txt
file.2003-01-04.txt
... and so on? I would like them to be named:
file_y2003m01d02.txt
file_y2003m01d04.txt
... etc.
In other words, file.2007-12-09.txt would become file_y2007m12d09. Is there a simple set of commands to do this?
Similarly I have another problem, where files are named file_y2003m02d01_grid.txt. I would like to know how to remove _grid from each filename, so that it matches the format I proposed above.
You can use the rename command:
rename 's/^file\.([0-9]{4})-([0-9]{2})-([0-9]{2})\.txt$/file_y$1m$2d$3.txt/' *
This uses Perl regular expression substitution to transform filenames. The command above says:
Find files starting ^ with file. (the . has to be escaped, otherwise it matches any character), followed by the captured () group [0-9]{4} (a digit, 4 times), then -, then another captured group of a digit twice, etc., and ending $ with .txt;
Then, rename those files to file_y followed by the first captured group $1, followed by m, followed by the second captured group $2, etc., and ending with .txt.
You should also be able to work out how to use the same command to solve your second problem, with what you no know about how rename works.
You can also use sed:
for example:
ls | while read f; do echo "mv $f $(echo $f | sed 's/\./_y/;s/-/m/;s/-/d/')"; done
This will show you the commands that bash will run. To actually do the move, remove the echo and quotes:
ls | while read f; do mv $f $(echo $f | sed 's/\./_y/;s/-/m/;s/-/d/'); done

Bash script to remove 'x' amount of characters the end of multiple filenames in a directory?

I have a list of file names in a directory (/path/to/local). I would like to remove a certain number of characters from all of those filenames.
Example filenames:
iso1111_plane001_00321.moc1
iso1111_plane002_00321.moc1
iso2222_plane001_00123.moc1
In every filename I wish to remove the last 5 characters before the file extension.
For example:
iso1111_plane001_.moc1
iso1111_plane002_.moc1
iso2222_plane001_.moc1
I believe this can be done using sed, but I cannot determine the exact coding. Something like...
for filename in /path/to/local/*.moc1; do
mv $filname $(echo $filename | sed -e 's/.....^//');
done
...but that does not work. Sorry if I butchered the sed options, I do not have much experience with it.
mv $filname $(echo $filename | sed -e 's/.....\.moc1$//');
or
echo ${filename%%?????.moc1}.moc1
%% is a bash internal operator...
This sed command will work for all the examples you gave.
sed -e 's/\(.*\)_.*\.moc1/\1_.moc1/'
However, if you just want to specifically "remove 5 characters before the last extension in a filename" this command is what you want:
sed -e 's/\(.*\)[0-9a-zA-Z]\{5\}\.\([^.]*\)/\1.\2/'
You can implement this in your script like so:
for filename in /path/to/local/*.moc1; do
mv $filename "$(echo $filename | sed -e 's/\(.*\)[0-9a-zA-Z]\{5\}\.\([^.]*\)/\1.\2/')";
done
First Command Explanation
The first sed command works by grabbing all characters until the first underscore: \(.*\)_
Then it discards all characters until it finds .moc1: .*\.moc1
Then it replaces the text that it found with everything it grabbed at first inside the parenthesis: /\1
And finally adds the .moc1 extension back on the end and ends the regex: .moc1/
Second Command Explanation
The second sed command works by grabbing all characters at first: \(.*\)
And then it is forced to stop grabbing characters so it can discard five characters, or more specifically, five characters that lie in the ranges 0-9, a-z, and A-Z: [0-9a-zA-Z]\{5\}
Then comes the dot '.' character to mark the last extension : \.
And then it looks for all non-dot characters. This ensures that we are grabbing the last extension: \([^.]*\)
Finally, it replaces all that text with the first and second capture groups, separated by the . character, and ends the regex: /\1.\2/
This might work for you (GNU sed):
sed -r 's/(.*).{5}\./\1./' file

How to rename a bunch of files with a specific pattern

I want to rename the files in a directory which are named with this pattern:
string1-number.html
for example:
English-5.html
what I want to do is to rename the files like this:
string2-number.string3
for example:
Dictionary-5.en
How can I do this?
I used this script, but nothing happened:
echo "English-5.html" | sed 's%\({English}\).\(\.*\)\(html\)%dictionary\2\en%'
I would suggest using the mmv tool: http://linux.dsplabs.com.au/mmv-copy-append-link-move-multiple-files-under-linux-shell-bash-by-wildcard-patterns-p5/
With that you can do:
mmv *-*.html Dictionary-#2.en
echo "English-5.html" | sed 's%English\(-[0-9][0-9]*.\)html%dictionary\1en%'
Explanation:
I'm looking for English
followed by a dash, one or more numbers, and a dot -[0-9][0-9]*. (I surround this part with escaped parenthesis to make it a group (group 1)).
followed by html
In the replacement text, I use \1 to output the contents of group 1, as well as the changed text.
You have 2 errors: The {...} is not required, and you confused \. and .
\. matches a literal dot, while . matches a single character.
echo "English-5.html" |
sed 's%\(English\)\(.*\)\.\(html\)%dictionary\2.en%'
This answer shows some minor optimizations for sed commands already posted and shows how to actually rename the files (in the current folder):
for f in *; do mv "$f" $(echo "$f" |\
sed 's/^English-\([0-9]\+\)\.html$/dictionary-\1\.en/'); done

Resources