Using util-linux rename command - linux

I've been attempting to use the util-linux version of rename (2011) to replace a specific string in all files with another. While I realize the perl version of rename would offer a solution, I can't figure out how to use this version of rename.
The specific example are a set of files (something--2013.mkv, somethingelse--2011.mkv), and I'm trying to remove the double dashes and replace with a space.

The problem is that rename uses getopt for argument parsing and thus has a special interpretation for double dash (--). -- signifies the end of the arguments.
A solution would be to avoid using -- in your command. One way to do this is to break your command into sub targets, e.g. translate single dash to underscore, then two underscores to single dash:
$ rename - _ *.mkv
$ rename __ - *.mkv
A less roundabout way to do this is to actually use the getopt behavior
$ rename -- -- - *.mkv

The rename from util-linux is in /usr/bin/rename.ul in Ubuntu. So you could use the rename.ul command.

mkdir TEMP
numbers=2011
find . -name "*.mkv" | while read filename
do
echo mv "$filename" "TEMP/somethingelse_"$((numbers++)).mkv
rm filename
done

Related

How do I delete the first delimiter of file names in linux?

I want to delete the first delimiter of file names in linux.
For example,
$ ls my_directory
a.b.c.txt a.b.d.txt a.b.e.txt
I want it to be like:
$ ls my_directory
ab.c.txt ab.d.txt ab.e.txt
I tried:
$ mv a.b* ab*
, but unfortunately this doesn't work.
What should I do?
Thank you in advance.
Use a replace once parameter expansion method if you're using Bash:
for f in a.b*; do
mv -i -- "$f" "${f/.}"
done
See Shell Parameter Expansion.
If you're using a POSIX shell, you can use ${f%%.*}${f#*.} or in the case of a known prefix like a.b, , simply ab${f#a.b}.

Copying files with even number in its name - bash

I want to copy all files from /usr/lib which ends with .X.0.0 where X is an even number. Is there a better way than the following one to select all the files?
ls /usr/lib | grep "[02468].0.0$"
My problem with this solutions is that in case there are files with names like "xy.800.0.0" I need to use the bracket three times etc.
Just use a glob expansion to match the files:
cp /usr/lib/*.*[02468].0.0 /path/to/destination
The shell expands this pattern to the list of files before passing them as arguments to cp.
Since you tagged Bash, you can make the match more strict by using an extended glob:
shopt -s extglob failglob
cp /usr/lib/*.*([0-9])[02468].0.0 /path/to/destination
This matches 0 or more other digits followed by an even digit, and doesn't run the command at all if no files match.
You could use extended grep regular expressions to only match even numbers:
ls -1q /usr/lib | grep -E "\.[0-9]*[02468].0.0$"
However, as Tom suggested, there are better options than parsing the output of ls. It's generally safer and faster to use glob expansion, and more maintainable to just put everything in a python script.

Remove part of filename with common delimiter

I have a number of files with the following naming:
name1.name2.s01.ep01.RANDOMWORD.mp4
name1.name2.s01.ep02.RANDOMWORD.mp4
name1.name2.s01.ep03.RANDOMWORD.mp4
I need to remove everything between the last . and ep# from the file names and only have name1.name2.s01.ep01.mp4 (sometimes the extension can be different)
name1.name2.s01.ep01.mp4
name1.name2.s01.ep02.mp4
name1.name2.s01.ep03.mp4
This is a simpler version of #Jesse's [answer]
for file in /path/to/base_folder/* #Globbing to get the files
do
epno=${file#*.ep}
mv "$file" "${file%.ep*}."ep${epno%%.*}".${file##*.}"
#For the renaming part,see the note below
done
Note : Didn't get a grab of shell parameter expansion yet ? Check [ this ].
Using Linux string manipulation (refer: http://www.tldp.org/LDP/abs/html/string-manipulation.html) you could achieve like so:
You need to do per file-extension type.
for file in <directory>/*
do
name=${file}
firstchar="${name:0:1}"
extension=${name##${firstchar}*.}
lastchar=$(echo ${name} | tail -c 2)
strip1=${name%.*$lastchar}
lastchar=$(echo ${strip1} | tail -c 2)
strip2=${strip1%.*$lastchar}
mv $name "${strip2}.${extension}"
done
You can use rename (you may need to install it). But it works like sed on filenames.
As an example
$ for i in `seq 3`; do touch "name1.name2.s01.ep0$i.RANDOMWORD.txt"; done
$ ls -l
name1.name2.s01.ep01.RANDOMWORD.txt
name1.name2.s01.ep02.RANDOMWORD.txt
name1.name2.s01.ep03.RANDOMWORD.txt
$ rename 's/(name1.name2.s01.ep\d{2})\..*(.txt)$/$1$2/' name1.name2.s01.ep0*
$ ls -l
name1.name2.s01.ep01.txt
name1.name2.s01.ep02.txt
name1.name2.s01.ep03.txt
Where this expression matches your filenames, and using two capture groups so that the $1$2 in the replacement operation are the parts outside the "RANDOMWORD"
(name1.name2.s01.ep\d{2})\..*(.txt)$

rename all files in folder through regular expression

I have a folder with lots of files which name has the following structure:
01.artist_name - song_name.mp3
I want to go through all of them and rename them using the regexp:
/^d+\./
so i get only :
artist_name - song_name.mp3
How can i do this in bash?
You can do this in BASH:
for f in [0-9]*.mp3; do
mv "$f" "${f#*.}"
done
Use the Perl rename utility utility. It might be installed on your version of Linux or easy to find.
rename 's/^\d+\.//' -n *.mp3
With the -n flag, it will be a dry run, printing what would be renamed, without actually renaming. If the output looks good, drop the -n flag.
Use 'sed' bash command to do so:
for f in *.mp3;
do
new_name="$(echo $f | sed 's/[^.]*.//')"
mv $f $new_name
done
...in this case, regular expression [^.].* matches everything before first period of a string.

Linux - rename all files by replacing last hyphen with '##'

Please anyone.
How do I in Linux rename a bunch of files like:
abc-def-0001.xxx
acb-def-0002.xxx
to:
abc-def##0001.xxx
...
I have tried several suggestions from SO like:
rename 's/(.*)-/$1##/' *.xxx
But didn't worked as expected in my environment.
You can use lookahead in your regex:
rename -n 's/-(?=\d)/##/' *.xxx
This will match & replace first _ that is followed by a digit.
However your pattern 's/(.*)-/$1##/' would also work for given examples but this assumes you're always replacing last underscore.
So I ended up using:
for i in *; do mv "$i" "`echo $i | sed "s/\(.*\)-/\1##/"`"; done
I think my version of the rename command does not support the perl expressions...

Resources