How to rename folders that contain consistent sub-string at the end using mv command? - macos

I have many folders with the following pattern:
$ ls
a-master 123-master abc123-master
I want them to be:
$ ls
a 123 abc123
During my research, I found this answer. But when I ran mv "$f" "${f/-master/}", I got mv: rename to : No such file or directory error and I'm not sure why.
I found many answers recommending rename package but I don't prefer it. I think it's possible to be done just by using mv command but I'm not entirely sure how.
Does is possible? If possible, what is the correct command for this case?
I'm looking for one liner command, a short and sweet one.

I am fetching details from the shared link-
for f in opencv_*; do mv "$f" "${f/.so/}"; done
The mv command is working on a loop where f is defined as a temporary variable, whereas the query posted does not have a variable. (f == "")
Example,
mkdir abc123-master
export F=abc123-master
mv $F ${F/-master/}
ls -rlt
abc123

Related

Changing name to files in bash respecting the number associated to each file

I have a bunch of files in bash named myfile1.sh, myfile2.sh, myfile3.sh... and so on. I would like to remove the sh part in each one of them, that is: rename to myfile1, myfile2, myfile3, ... Do you have a suggestion to do it all at once?
Thanks in advance.
for i in *.sh; do mv "$i" "${i%.sh}"; done
If you have the rename command, you can use it:
rename 's/\.sh$//' *.sh
A bash one-liner can be:
for f in *.sh; do mv "$f" "${f%.sh}"; done

How to modify file names in bash

I have a directory like: /data/work/files/
calldata_phonecalls_2131201401_01.zip
calldata_phonecalls_7373201401_02.zip
In this directory I want to create new files corresponding to the zipfiles like , but modifying a small part of the name in BASH:
calldata_calllog_2131201401_01.tsv
calldata_calllog_7373201401_02.tsv
pl note "phonecalls" changed to "calllog"
Pl help.
Using Shell Parameter Expansion and basename:
for f in /data/work/files/*.zip; do
mv "$f" "$(basename "${f/phonecalls/calllog}" .zip).tsv"
done
Using rename (part of perl distribution):
rename 's/phonecalls/calllog/;s/\.zip$/.tsv/' /data/work/files/*.zip
Using rename :
Using one version of rename:
rename 's/^fgh/jkl/' fgh*
Using another version of rename :
rename fgh jkl fgh*
You should check your platform's man page to see which of the above applies.
Using mv:
find ./ -name "*.xyz\[*\]" | while read line
do
mv "$line" ${line%.*}.xyz
done
Another way
ls -1 | nawk '/foo-bar-/{old=$0;gsub(/-\(.*\)/,"",$0);system("mv \""old"\" "$0)}'
Yet another:
for f in fgh*; do mv $f $(echo $f | sed 's/^fgh/jkl/g'); done
There are several other answers under stackoverflow and superuser pages:
Copied/summarized from the following links:
Rename multiple files in Unix
How to use mv command to rename multiple files in unix?

Batch mv or rename in bash script - append date as a suffix

After much searching and trial and error, I'm unable to do a batch mv or rename on a directory of files. What I'd like to do is move or rename all files in a directory so that the mv'd or renamed file has $date (+ '%Y%d%m') added to the original suffix.
All the original files have unique prefixes but are either .xml or .txt so I'd like to go from org_prefix.org_suffix -> org_prefix.org_suffix.DATE
I've tried this:
$ mv /directory/* /directory/*$(date (+ '%Y%m%d')
but always get /directory/*.actualdate' is not a directory error.
I've tried this:
$ for f in *; do mv $ $f.$(date +'_%m%d%y'); done
but I get mv: cannot stat '$'; No such file or directory
Lastly, I've even tried this:
$ rename 's/*/.test/' *
just to see if I could change all the files to org_prefix.test but nothing happens (no errors, nada, zip)
Any help greatly appreciated.
The proper way to loop through files (and e.g., print their name) in the current directory is:
for file in *; do
echo "$file"
done
How will you append the date? like so, of course:
for file in *; do
echo "$file.$(date +%Y%m%d)"
done
And how are you going to do the move? like so, of course:
for file in *; do
mv -nv -- "$file" "$file.$(date +%Y%m%d)"
done
I've added:
-v so that mv be verbose (I like to know what's happening and it always impresses my little sister to watch all these lines flowing on the screen).
-n so as to no overwrite an otherwise existing file. Safety first.
-- just in case a file name starts with a hyphen: without --, mv would confuse with an option. Safety first.
If you just want to look through the files with extension .banana, replace the for with:
for file in *.banana; do
of for files that contain the word banana:
for file in *banana*; do
and so on.
Keep up with the bananas!
$ mv /directory/* /directory/*$(date (+ '%Y%m%d')
This does not work, because the * is expanded to a list of all files, so after the expansion the command will be something like:
mv /directory/file1 /directory/file2 /directory/file3 /directory/file1_date /directory/file1_date ...
So you have specified many destinations, but the syntax for mv allows only one single destination.
for f in *; do mv $ $f.$(date +'_%m%d%y'); done
Here you forgot the f after the $, that's why you get the error message.
for f in *; do mv $f $f.$(date +'%m%d%y'); done
I think this should work now, but don't forget to quote all the variables!
Finally:
for f in *; do mv "$f" "$f.$(date +'%m%d%y')"; done
Edit: When there are characters directly after a variable, it's good practice to use {} to make clear that they are not part of the variable name:
for f in *; do mv "$f" "${f}.$(date +'%m%d%y')"; done

Rename all files in directory from $filename_h to $filename_half?

Dead simple.
How do I rename
05_h.png
06_h.png
to
05_half.png
06_half.png
At least, I think it's simple, but it's hard to Google for this kind of thing unless you already know.
Thanks....
Just use bash, no need to call external commands.
for file in *_h.png
do
mv "$file" "${file/_h.png/_half.png}"
done
Do not add #!/bin/sh
For those that need that one-liner:
for file in *.png; do mv "$file" "${file/_h.png/_half.png}"; done
Try rename command:
rename 's/_h.png/_half.png/' *.png
Update:
example usage:
create some content
$ mkdir /tmp/foo
$ cd /tmp/foo
$ touch one_h.png two_h.png three_h.png
$ ls
one_h.png three_h.png two_h.png
test solution:
$ rename 's/_h.png/_half.png/' *.png
$ ls
one_half.png three_half.png two_half.png
for f in *.png; do
fnew=`echo $f | sed 's/_h.png/_half.png/'`
mv $f $fnew
done
Or in one-liner:
for f in *.png; do mv "$f" "$(echo $f | sed 's/_h.png$/_half.png/g')"; done
Are you looking for a pure bash solution? There are many approaches, but here's one.
for file in *_h.png ; do mv "$file" "${file%%_h.png}_half.png" ; done
This presumes that the only files in the current directory that end in _h.png are the ones you want to rename.
Much more specifically
for file in 0{5..6}_h.png ; do mv "$file" "${file/_h./_half.}" ; done
Presuming those two examples are your only. files.
For the general case, file renaming in has
been covered
before.
Use the rename utility written in perl.
Might be that it is not available by default though...
$ touch 0{5..6}_h.png
$ ls
05_h.png 06_h.png
$ rename 's/h/half/' *.png
$ ls
05_half.png 06_half.png
for i in *_h.png ; do
mv $i `echo "$i"|awk -F'.' '{print $1"alf."$2}'`
done
I had a similar question:
In the manual, it describes rename as
rename [option] expression replacement file
so you can use it in this way
rename _h _half *.png
In the code:
'_h' is the expression that you are looking for.
'_half' is the pattern that you want to replace with.
'*.png' is the range of files that you are looking for your possible target files.
Hope this can help c:
Another approach can be manually using batch rename option
Right click on the file -> File Custom Commands -> Batch Rename
and you can replace h. with half.
This will work for linux based gui using WinSCP etc
One liner:
for file in *.php ; do mv "$file" "_$file" ; done
Although the answer set is complete, I need to add another missing one.
for i in *_h.png;
do name=`echo "$i" | cut -d'_' -f1`
echo "Executing of name $name"
mv "$i" "${name}_half.png"
done
I had to rename the prefix of files and I found this answer with a solution like this:
for i in h_*; do mv ${i/#h_/half_}; done
If pattern begins with #, it must match at the beginning of the
expanded value of parameter. If pattern begins with %, it must match
at the end of the expanded value of parameter.
from man bash
Use the rename utility:
rc#bvm3:/tmp/foo $ touch 05_h.png 06_h.png
rc#bvm3:/tmp/foo $ rename 's/_h/_half/' *
rc#bvm3:/tmp/foo $ ls -l
total 0
-rw-r--r-- 1 rc rc 0 2011-09-17 00:15 05_half.png
-rw-r--r-- 1 rc rc 0 2011-09-17 00:15 06_half.png

Glob renaming in bash

I'm fairly new to bash so sorry if this is kind of a basic question. I was trying to rename a bunch of mp3 files to prepend 1- to their filenames, and mv *.mp3 1-*.mp3 didn't work unfortunately. So I tried to script it, first with echo to test the commands:
for f in *.mp3 ; do echo mv \'$f\' \'1-$f\'; done
Which seems to output the commands that I like, so I removed the echo, changing the command to
for f in *.mp3 ; do mv \'$f\' \'1-$f\'; done
Which failed. Next I tried piping the commands onward like so
for f in *.mp3 ; do echo mv \'$f\' \'1-$f\'; done | /bin/sh
Which worked, but if anyone could enlighten me as to why the middle command doesn't work I would be interested to know. Or if there is an more elegant one-liner that would do what I wanted, I would be interested to see that too.
I think you have to change the command to
for f in *.mp3 ; do mv "$f" "1-$f"; done
Otherwise you would pass something like 'file1.mp3' and '1-file1.mp3' to mv (including the single quotes).
Dry run:
rename -n 's/^/1-/' *.mp3
Remove the -n if it looks correct to run the command. man rename for details.

Resources