Reputation: 1048
Ubuntu 16.04
Bash 4.4.20
Rename 0.20
I have hundreds of files that get copied to a folder each day. The folder name is different each day so the files on the inside of the folder have to be renamed
Here is an example of the files after being copied to the folder.
2019-11-30_hs5_felix.doggie.com_1112.garage
2019-12-01_hs5_ralph.doggie.com_1112.garage
2019-12-04_hs5_sartah.doggie.com_1112.garage
2019-12-05_hs5_felix.doggie.com_1112.garage
2019-12-07_hs5_ggg.doggie.com_1112.garage
2019-12-12_hs5_fex.doggie.com_1112.garage
2019-12-19_hs5_sioia.doggie.com_9999.garage
2019-12-21_hs5_felix.doggie.com_1002.garage
2019-12-22_hs5_sonia.doggie.com_1112.garage
2019-12-25_hs5_isabel.doggie.com_1106.garage
Here is the pattern that will be the same:
same_same_"${one}".same.same_"${two}".same
So the variables will represent two words we will use to rename all the files to and the files need to look like the following after being renamed:
one="ssss"
two="1234"
2019-11-30_hs5_sssss.doggie.com_1234.garage
2019-12-01_hs5_sssss.doggie.com_1234.garage
2019-12-04_hs5_sssss.doggie.com_1234.garage
2019-12-05_hs5_sssss.doggie.com_1234.garage
2019-12-07_hs5_sssss.doggie.com_1234.garage
2019-12-12_hs5_sssss.doggie.com_1234.garage
2019-12-19_hs5_sssss.doggie.com_1234.garage
2019-12-21_hs5_sssss.doggie.com_1234.garage
2019-12-22_hs5_sssss.doggie.com_1234.garage
2019-12-25_hs5_sssss.doggie.com_1234.garage
The final product is more important than how it is done so we can use any commands to get there.
Upvotes: 1
Views: 234
Reputation: 58400
This also may work for you - (GNU parallel):
parallel 'mv {1} {=1 s/(_.*_)[^.]+(.*_)[^.]+/$1$arg[2]$2$arg[3]/ =}' ::: * ::: ssss ::: 1234
Use GNU parallel to eliminate forloop and shell variables. The {=n ... =}
allows the use of perl commands on the n'th positional replacement string. In this case, use the substitution command to replace parts of each file name garnered from ::: *
.
Note: Before executing this command, it is always good practice to insert the --dry-run
option and inspect its output before running it live.
Upvotes: 2
Reputation: 7277
i came out with this for your filenames(2019-12-19_hs5_sioia.doggie.com_9999.garage)
one="ssss"
two="1234"
for file in *; { name=${file//_[0-9]*.g/_$two.g}; name=${name//_*.d/_$one.d}; mv $file $name; }
This method uses variable substitutions ${var//pattern/change}
Upvotes: 1
Reputation: 22012
According to the pattern same_same_"${one}".same.same_"${two}".same
, how about:
one="ssss"
two="1234"
for f in *.*; do
IFS=_ read -ra a <<< "$f"
a[2]="${one}.${a[2]#*.}"
a[3]="${two}.${a[3]#*.}"
(IFS=_; mv -- "$f" "${a[*]}")
done
It first splits the filename on _
, replaces the specified positions with
the variables, then merges them again as a new filename.
Upvotes: 2
Reputation: 84561
Without rename, you can actually change the names of the files making both substitutions of "$one"
and "$two"
using the mv
command and a command-substitution using sed
. This eliminates the "Which version of rename do I have?"
For example, in your case, you can change to the directory containing the files, and do:
one="ssss"
two="1234"
for i in *; do
mv "$i" "$(sed 's/^\(.*hs5_\)[^.]*\([.].*com_\)[0-9]*\(.*$\)/\1'"$one"'\2'"$two"'\3/' <<< "$i")"
done
Which makes use of sed
normal substitution command making use of three-capture groups and backreferences.
Explanation
The sed
substitution command is sed 's/find/replace/'
where in your case the find is broken into the parts:
^\(.*hs5_\)
match from the beginning of the filename through "hs5_"
capturing the text within a capture group of \( ... \)
using basic regular expressions to be reinserted with the first backreference \1
;"hs5_"
on we match [^.]*
a sequence of characters not containing a '.'
;'.'
through "com_"
capturing \([.].*com_\)
to reinsert with the second backreference \2
; and finally\(.*$\)
for reinsertion as \3
For the replace portion, we just include the captured text making the variable substitutions:
\1'"$one"'\2'"$two"'\3
(note: the quoting is very specific. The parts of the sed
command are enclosed in single quotes which the shell variables are enclosed in double quotes, along with the complete command substitution.
The basic move of the file in accomplished with mv "$i" "$(sed ... <<< "$i")
where the filename is fed to the sed
command using a bash-only Here-String <<<
which redirects the contents of the variable to the sed
command on stdin
allowing sed
to make the substitutions completing the move.
Upvotes: 2