Reputation: 137
I would like to rename file based on parent/subparent directories name.
For example: test.xml file located at
/usr/local/data/A/20180101
/usr/local/data/A/20180102
/usr/local/data/B/20180101
how to save test.xml file in /usr/local/data/output as
A_20180101_test.xml
A_20180102_test.xml
b_20180101_test.xml
tried shall script as below but does not help.
#!/usr/bin/env bash
target_dir_path="/usr/local/data/output"
for file in /usr/local/data/*/*/test.xml; do
l1="${file%%/*}"
l2="${file#*/}"
l2="${l2%%/*}"
filename="${file##*/}"
target_file_name="${l1}_${l2}_${filename}"
echo cp "$file" "${target_dir_path}/${target_file_name}"
done
Anything i am doing wrong in this shall script?
Upvotes: 1
Views: 1803
Reputation: 23667
if you have perl
based rename
command
$ for f in tst/*/*/test.xml; do
rename -n 's|.*/([^/]+)/([^/]+)/(test.xml)|./$1_$2_$3|' "$f"
done
rename(tst/A/20180101/test.xml, ./A_20180101_test.xml)
rename(tst/A/20180102/test.xml, ./A_20180102_test.xml)
rename(tst/B/20180101/test.xml, ./B_20180101_test.xml)
-n
option is for dry run, remove it after testingtst
to /usr/local/data
and ./
to /usr/local/data/output/
for your usecase.*/
to ignore file path([^/]+)/([^/]+)/(test.xml)
capture required portions$1_$2_$3
re-arrange as requiredUpvotes: 1
Reputation: 2375
I've modified your code a little to get it to work. See comments in code
target_dir_path=""/usr/local/data/output"
for file in /usr/local/data/*/*/test.xml; do
tmp=${file%/*/*/*}
curr="${file#"$tmp/"}" # Extract wanted part of the filename
mod=${curr//[\/]/_} # Replace forward slash with underscore
mv "$file" "$target_dir_path$mod" # Move the file
done
Upvotes: 2
Reputation: 12438
You can use the following command to do this operation:
source_folder="usr/local/data/";target_folder="target"; find $source_folder -type f -name test.xml | awk -v targetF=$target_folder 'BEGIN{FS="/"; OFS="_"}{printf $0" "; print targetF"/"$(NF-2),$(NF-1),$NF}' | xargs -n2 cp;
or on several lines for readibility:
source_folder="usr/local/data/";
target_folder="target";
find $source_folder -type f -name test.xml |\
awk -v targetF=$target_folder 'BEGIN{FS="/"; OFS="_"}{printf $0" "; print targetF"/"$(NF-2),$(NF-1),$NF}' |\
xargs -n2 cp;
where
target_folder
is your target foldersource_folder
is your source folderfind
command will search for all the test.xml
named files present under this source folderawk
command will receive the target folder as a variable to be able to use it, then in the BEGIN
bloc you define the field separator and output field separator, then you just print the initial filename as well as the new onecp
command and the trick is doneTESTED:
TODO:
you will just need to set up your source_folder
and target_folder
variables with what is on your environment and eventually put it in a script and you are good to go!
Upvotes: 2