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

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...

Related

How to get filename without version part and replace with older versions?

I have a folder containing new jar files and I need to replace them on the old version files on a different folder, need to replace even if the version is same.
My sample file name:
SC_S_SyncUp_V3.0.0-a7 20211221.jar
gudusoft.gsqlparser-2.3.0.9.jar
When I try with below command, it is getting only the first part "SC".
ls | cut -d "_" -f 1
SC
Can anyone please guide how to do this.
If you use "ls -1", "ls" will put each file on a line. Then a "for loop" would process each filename. "basename" can remove known suffixes, or you can use "sed" to remove everything past the last ".".
Putting it all together would be:
for file in $(ls -1)
do
f=$(echo $file | sed 's/\.[^\.]*$//')
echo $f;
done
I'm not sure what you want to do with "replace with older versions".

shell script to list file names alone in a directory & rename it [duplicate]

This question already has answers here:
How can I remove the extension of a filename in a shell script?
(15 answers)
Closed 6 years ago.
I'm new to scripting concept.. I have a requirement to rename multiple files in a directory like filename.sh.x into filename.sh
First I tried to get the file names in a particular directory.. so i followed the below scripting code
for entry in PathToThedirectory/*sh.x
do
echo $entry
done
& the above code listed down all the file names with full path..
But my expected o/p is : to get file names alone like abc.sh.x,
so that I can proceed with the split string mechanism to perform rename
operation easily...
help me to solve this ... Thanks in advance
First approach trying to follow OP suggestions:
for i in my/path/*.py.x
do
basename=$(basename "$i")
mv my/path/"$basename" my/path/"${basename%.*}"
done
And maybe, you can simplify it:
for i in my/path/*.py.x
do
mv "$i" "${i%.*}";
done
Documentation regarding this kind of operation (parameter expansion): https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html
In particular:
${parameter%word} : The word is expanded to produce a pattern just as in filename expansion. If the pattern matches a trailing portion of the expanded value of parameter, then the result of the expansion is the value of parameter with the shortest matching pattern (the ‘%’ case) or the longest matching pattern (the ‘%%’ case) deleted
So, ${i%.*} means:
Take $i
Match .* at the end of its value (. being a literal character)
Remove the shortest matching pattern
Look into prename (installed together with the perl package on ubuntu).
Then you can just do something like:
prename 's/\.x$//' *.sh.x
In ksh you can do this:
for $file in $(ls $path)
do
new_file=$(basename $path/$file .x)
mv ${path}/${file} ${path}/${new_file}
done
This should do the trick:
for file in *.sh.x;
do
mv "$file " "${file /.sh.x}";
done
Running this rename command from the root directory should work:
rename 's/\.sh\.x$/.sh/' *.sh.x
for i in ls -la /path|grep -v ^d|awk '{print $NF}'
do
echo "basename $i"
done
it will give u the base name of all files or you can try below
find /path -type f -exec basename {} \;

Capture part of name so that I can loop in linux

how do i capture a pattern in a filename and use that to do in linux?
example in a folder contains these files:
BBB137O19_rc.fa
BBB921N08_cleaned.fa
BBB002O19_cc.fa
I would like to capture the front part of the filename and use that to do things like renaming, run a program etc. Apparently, basename is greedy and works for everything before the extension.
thanks in advance
I tried this command but failed
for i in *.fa; base=$(basename $i _*.fa); comb="${base}_ec.txt"; mv ec.txt $comb; done
You can use BASH string manipulations:
s='BBB921N08_cleaned.fa'
echo "${s%%_*}"
BBB921N08
Also, sed can be used:
echo "$i"|sed 's/_.*//'
This removes _ and any character (.) occuring any number of times after it (*).
Sed with its regular expressions is especially useful, if you have more complicated patterns to process.

Using util-linux rename command

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

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