LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   renaming files to use their path in awk (https://www.linuxquestions.org/questions/linux-newbie-8/renaming-files-to-use-their-path-in-awk-4175712260/)

atjurhs 05-17-2022 03:54 PM

renaming files to use their path in awk
 
hi guys,

i'm trying to rename a csv file using the path to that file as part of it's name. here's my situation

Code:

filename.csv is in path /home/abc1/def1/filename.csv
after running an awk script that i've written on filename.csv i need the script to output

Code:

filename.csv > /home/abc1/def1/abc1_def1_filename.csv
how do i make the path as part of the file's new name?

teckk 05-17-2022 04:35 PM

Examples:
Code:

f="/home/abc1/def1/filename.csv"

echo ${f%.*}
echo ${f#*.}
echo ${f##*/}
echo ${f%/*}
awk -F/ '{print $3}' <<< "$f"
awk -F/ '{print $4}' <<< "$f"


grail 05-17-2022 10:10 PM

Not sure I follow the question, but in awk the file name is in the variable FILENAME and the split function can be used to break up the parts.

The question is a bit vague on whether this is just an output from the awk script or if you want to redirect it to that new file (the above can do both)

syg00 05-17-2022 10:26 PM

Given previous posts, I'd say this is using the wrong tool for the job. A spanner can be used to bang in a nail, but it ain't a proper hammer ...

MadeInGermany 05-18-2022 12:31 AM

Using the variable modifiers in post 2
Code:

pn="/home/abc1/def1/filename.csv"
fn=${pn##*/}
dir=${pn%/$fn}
dn2=${dir##*/}
dd=${dir%/$dn2}
dn1=${dd##*/}
opn=${dir}/${dn1}_${dn2}_${fn}
echo "$pn" ">" "$opn"


atjurhs 05-18-2022 12:29 PM

hey guys,

MadeInGermany i see what you're doing, and it works for me, thanks!

so i've included your code as part of the script that i run
Code:

pn="/home/abc/def/filename.csv"
fn=${pn##*/}
dir=${pn%/$fn}
dn2=${dir##*/}
dd=${dir%/$dn2}
dn1=${dd##*/}
dn1dn2fn=${dn1}_${dn2}_${fn}
awk 'do good stuff' filename.csv > $dn1dn2fn

and i got a file that did good stuff and called
Code:

abc_def_filename.csv
so it worked, YAY, step one is complete.

having learned from this, my next step is that my csv file is imbedded 8 directories deep. so i thought i would just keep creating the dd and dn variables as you have? and end up with something like
Code:

pn="/home/abc/def/ghi/jkl/mno/pqr/stu/filename.csv"
fn=${pn##*/}
dir=${pn%/$fn}
dn8=${dir##*/}
dd8=${dir%/$dn8}
dn7=${dd8##*/}
dd7=${dd8/$dn7}
dn6=${dd7##*/}
dd6=${dd7/$dn6}
dn5=${dd6##*/}
dd5=${dd6/$dn5}
.
.
.
to eventually build

dn1dn2dn3dn4dn5dn6dn7dn8fn = ${dn1}_${dn2}_${dn3}_${dn4}_${dn5}_${dn6}_${dn7}_${dn8}_${fn}

Code:

then run the awk script with filename.csv > $dn1dn2dn3dn4dn5dn6dn7dn8fn

or even pick and choose dn3dn5dn6dn7fn=${dn3}_${dn5}_${dn6}_${dn7}_${fn}

and then filename.csv > $dn3dn5dn6dn7fn

anyways, it's pretty ugly, but it works :) maybe there's an easier way?

MadeInGermany 05-18-2022 01:14 PM

If the path is too deep or the depth is unknown, then in bash you can use other variable modifiers
Code:

pn="/home/abc/def/filename.csv"
dn=${pn#/*/}
ndn=${dn//"/"/_}

The # is like the ## but * wildcards expand to the minimum.
The //string1/string2 substitutes all string1 by string2
(While /string1/string2 would substitute one string1)
A / character is conflicting and must be escaped \/ or "/"

grail 05-19-2022 10:30 AM

As advised, awk can just do it all:
Code:

$ awk 'BEGIN{fn="/home/abc/def/ghi/jkl/mno/pqr/stu/filename.csv";split(fn,arr,"/");print "your stuff" > arr[2]"_"arr[4]"_"arr[6]".csv"}'
$ ls
home_def_jkl.csv
$ cat home_def_jkl.csv
your stuff

Of course you just change fn for FILENAME when you call it like:
Code:

awk '<do some magic>{split(FILENAME,arr,"/"); print > <your array combo here>}' /home/abc/def/ghi/jkl/mno/pqr/stu/filename.csv

atjurhs 05-19-2022 10:46 AM

now that i have a unique filename for each file i need to copy all the files into a "common" directory

Code:

/home/abc/def/ghi/123/mno/pqr/stu/filename.csv > /home/common/abc_def_ghi_123_mno_pqr_stu_filename.csv
/home/abc/def/ghi/456/mno/pqr/stu/filename.csv > /home/common/abc_def_ghi_456_mno_pqr_stu_filename.csv
/home/abc/def/ghi/789/mno/pqr/stu/filename.csv > /home/common/abc_def_ghi_789_mno_pqr_stu_filename.csv
.
.
.

then i'll run another awk script on these files.

i know, it's a cumbersome way of getting the job done, but i know how to run the second awk script, what it needs, and it does what i need done

pan64 05-19-2022 11:10 AM

you can split the filename like this:
Code:

pn=/home/abc/def/ghi/123/mno/pqr/stu/filename.csv
farr=( ${pn//\// } )
new_pn="/${farr[0]}/${farr[1]}/${farr[2]}_${farr[3]}_${farr[4]}"
mv "$pn" "$new_pn"

Or you can just replace / to _ after the common root:
Code:

pn=/home/abc/def/ghi/123/mno/pqr/stu/filename.csv
root=/home/abc/def/
pn2=${pn:${#root}}
new_pn="$root/${pn2//\//_}"

(not tested)

atjurhs 05-19-2022 12:52 PM

pan64

i don't follow you.

once i have a unique filename (using the method that we worked out above) i want to copy that file into a common folder where i will end up having a bunch of files with almost the same names (but slightly different), and then i will run my second awk script on all those files.

pan64 05-19-2022 12:55 PM

in that case replace the last line (or add):
Code:

awk 'very good script' "$pn" > "$new_pn"

atjurhs 05-19-2022 01:41 PM

just doing
Code:

awk 'very good script' filename.csv > /home/common_dir/abc_def_ghi_123_mno_pqr_stu_filename.csv
awk 'very good script' filename.csv > /home/common_dir/abc_def_ghi_456_mno_pqr_stu_filename.csv
awk 'very good script' filename.csv > /home/common_dir/abc_def_ghi_789_mno_pqr_stu_filename.csv
.
.
.

worked fine, it just means i have to cd down into each dir to run the awk script
Code:

/home/abc/def/ghi/123/mno/pqr/stu/
/home/abc/def/ghi/123/mno/pqr/stu/
/home/abc/def/ghi/123/mno/pqr/stu/
.
.
.

kind of a pain in the butt, but it gets the csv files down into the common_dir which is where i'll run a different 'do good stuff' awk script

grail 05-19-2022 11:40 PM

Assuming you are using gawk, again there is no issue to have multiple scripts.

Simply use the BEGIN_FILE{} declarative, use the split command on FILENAME as suggested and make your new file name and then simply redirect the output to the new file in whatever location you like.
Code:

awk 'BEGIN_FILE{split(FILENAME,pieces,"/");filename=<make your new file name here>;path=/path/to/new/location/filename}<do your magic on file while redirecting to "path">' <list of files here using full path name


All times are GMT -5. The time now is 02:31 AM.