replacing filenames with parent folder name without changing file endings - rename

Im struggling replacing filenames with parent folder name and conserving the different file endings.
Example;
.sp1/4287/4287/iho.cst
.sp1/4287/4287/iho.dbf
.sp1/4287/4287/iho.prj
.sp1/4287/4287/iho.shp
.sp1/4287/4287/iho.shx
renamed to;
.sp1/4287/4287/4287.cst
.sp1/4287/4287/4287.dbf
.
.
.
Im currently trying out zsh shell using zmv.
zmv '(*)/*' '$1/$1'
But this is matching all. I don't get how to escape the file endings (if possible). Also tried rename but without success.
Since I have multiple sp folders (sp2, sp3, ..spN) and since each e.g. sp1/ contain a lot of subfolders like 4287 with the same type of files, Im seeking a batch solution.
Any pointers would be appreciated.
UPDATE
This works when in spN/XXXX/;
zmv '(*)/*.(*)' '$1/$1.$2';
How can I write a loop going through the spN/XXXX/ folders and executing the above zmv code?
#!/usr/bin/env zsh
source ~/.zshrc
for i in ./*;
for y in i;
do
zmv '(*)/*.(*)' '$1/$1.$2';
done

I'm not really familiar with zmv, but I guess this will do it:
zmv '(*)/*.(*)' '$1/$1.$2'

I don't know zmv but try this script:
while read file
do
prefix=$(echo $file | sed 's|\(.*\)/.*$|\1|');
parent=$(echo $file | sed 's|.*/\([^/]\+\)/[^/]\+$|\1|');
child=$(echo $file | sed 's|.*/\([^.]\+\).*$|\1|');
ext=$(echo $file | sed 's|.*/[^.]\+\.\(.\+\)$|\1|');
mv "$prefix/$child.$ext" "$prefix/$parent.$ext"
done < <(find -type f)
EDIT: The first version doesn't work if the files or directories contains spaces.

Related

How to quickly rename my files on macOS or linux from CLI?

Here're my source files.
e2f9eb91-645f-408a-9241-66490b61a617_file-module-1.txt
d20f06a8-4de1-4da0-8175-93e9b2d81c42_file-module-2.txt
6740a19f-e1a0-43da-9a01-9e873238360e_file-module-3.txt
.
.
.
I need to figure it out a way to rename all the files to remove the first 36 characters up to _file or replacing as something else. I am expecting all the files are as below.
_file-module-1.txt or Yong_file-module-1.txt
_file-module-2.txt or Yong_file-module-2.txt
_file-module-3.txt or Yong_file-module-3.txt
.
.
.
Thanks in advance!
You can use rename like this:
rename --dry-run 's/.*_file/Yong_file/' *.txt
If you are on macOS, you can install rename with homebrew:
brew install rename
If you use mac, you can simply try this via UI:
https://support.apple.com/en-us/guide/mac-help/mchlp1144/mac
Or if you want to try those work via CLI:
https://www.howtogeek.com/423214/how-to-use-the-rename-command-on-linux/
(read from Renaming Multiple Files with mv)
This might help also; sed commands of linux:
https://www.geeksforgeeks.org/sed-command-in-linux-unix-with-examples/
and another stackoverflow article: bash substitute first character in every line
Easiest way to do this would be to use a combination of find, sed and xargs.
find . -name '*.txt' | sed 'p;s/.*_file/Yong_file/' | xargs -n2 mv
This finds text files in the current working directory, echoes the original file name (p) and then a modified name (s/.*_file/Yong_file/) and feeds it all to mv in pairs (xargs -n2).
If you would use zsh, you could do a
autoload zmv # Because zmv is not active by default
zmv '????????????????????????????????????(*module*txt)' '_$1'
Since you want to use bash, you could steal it from zsh and use it within bash like this:
zsh -c "autoload zmv; zmv '????????????????????????????????????(*module*txt)' '_$1'"
(These should be 36 question marks; better you count them again instead of blindly copying this code).

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.

Need help editing multiple files using sed in linux terminal

I am trying to do a simple operation here. Which is to cut a few characters from one file (style.css) do a find a replace on another file (client_custom.css) for more then 100 directories with different names
When I use the following command
for d in */; do sed -n 73p ~/assets/*/style.css | cut -c 29-35 | xargs -I :hex: sed -i 's/!BGCOLOR!/:hex:/' ~/assets/*/client_custom.css $d; done
It keeps giving me the following error for all the directories
sed: couldn't edit dirname/: not a regular file
I am confused on why its giving me that error message explicitly gave the full path to the file. It works perfectly fine without a for loop.
Can anyone please help me out with this issue?
sed doesn't support folders as input.
for d in */;
puts folders into $d. If you write sed ... $d, then BASH will put the folder name into the arguments of sed and the poor tool will be confused.
Also ~/assets/*/client_custom.css since this will expand to all the files which match this pattern. So sed will be called once with all file names. You probably want to invoke sed once per file name.
Try
for f in ~/assets/*/client_custom.css; do
... | sed -i 's/!BGCOLOR!/:hex:/' $f
done
or, even better:
for f in ~/assets/*/client_custom.css; do
... | sed 's/!BGCOLOR!/:hex:/' "${f}.in" > "${f}"
done
(which doesn't overwrite the output file). This way, you can keep the "*.in" files, edit them with the patterns and then use sed to "expand" all the variables.

Move files and rename - one-liner

I'm encountering many files with the same content and the same name on some of my servers. I need to quarantine these files for analysis so I can't just remove the duplicates. The OS is Linux (centos and ubuntu).
I enumerate the file names and locations and put them into a text file.
Then I do a for statement to move the files to quarantine.
for file in $(cat bad-stuff.txt); do mv $file /quarantine ;done
The problem is that they have the same file name and I just need to add something unique to the filename to get it to save properly. I'm sure it's something simple but I'm not good with regex. Thanks for the help.
Since you're using Linux, you can take advantage of GNU mv's --backup.
while read -r file
do
mv --backup=numbered "$file" "/quarantine"
done < "bad-stuff.txt"
Here's an example that shows how it works:
$ cat bad-stuff.txt
./c/foo
./d/foo
./a/foo
./b/foo
$ while read -r file; do mv --backup=numbered "$file" "./quarantine"; done < "bad-stuff.txt"
$ ls quarantine/
foo foo.~1~ foo.~2~ foo.~3~
$
I'd use this
for file in $(cat bad-stuff.txt); do mv $file /quarantine/$file.`date -u +%s%N`; done
You'll get everyfile with a timestamp appended (in nanoseconds).
You can create a new file name composed by the directory and the filename. Thus you can add one more argument in your original code:
for ...; do mv $file /quarantine/$(echo $file | sed 's:/:_:g') ; done
Please note that you should replace the _ with a proper character which is special enough.

Batch rename of files with similar names

I have a series of files named like such:
file 1.jpeg
file 2.jpeg
file 3.jpeg
...
file 40.jpeg
I would like remove the space from all of their filenames without having to individually do it. I know its possible using something like: file{1,40}.jpeg or something like that but i can't remember and I don't even know how to search for it.
Thanks!
EDIT: linux
http://www.google.es/search?q=shell+rename+similar+files+in+a+directory
The first result is http://www.debian-administration.org/articles/150
Using the perl rename command [...] we can also, for example, strip spaces from filenames with this:
~$ rename 's/ //' *.jpeg
In other posts I've found this kind of commands that do not require perl:
for f in *; do mv "$f" `echo $f | tr --delete ' '`; done
I've not tried any of them.

Resources