0

I have the following command:

find . -mtime -5 -type f -exec ls -ltr {} \; | awk '{print "cp -p "$9" "$7}'

the output is like:

cp -p ./18587_96xxdata.txt 10
cp -p ./16947_96xxdata.txt 8
cp -p ./32721_96xxdata.txt 9
cp -p ./32343_96xxdata.txt 9
cp -p ./32984_96xxdata.txt 10

But I want the last part of the output to be always 2 digits, such as:

cp -p ./18587_96xxdata.txt 10
cp -p ./16947_96xxdata.txt 08
cp -p ./32721_96xxdata.txt 09
cp -p ./32343_96xxdata.txt 09
cp -p ./32984_96xxdata.txt 10

I tried different variations of %02d, but not getting what I want.

Here's one I tried:

find . -mtime -5 -type f -exec ls -ltr {} \; | awk '{print "cp -p " $9 " "("%02d", $7)}' 

Should I be using printf, and if so, how exactly?

Thank you!

2 Answers 2

3

See https://mywiki.wooledge.org/ParsingLs and https://mywiki.wooledge.org/Quotes and then do this instead:

$ find . -mtime -5 -type f -printf "cp -p '%p' '%Ad'\n"
cp -p './bbbb.csv' '09'
cp -p './cccc.csv' '10'
cp -p './out1.txt' '09'
cp -p './out2.txt' '05'
5
  • could you please explain your answer a little further. I don't think I understand %p and %Ad parts. What if I want to print different columns (from the ls -l output) right next to the file name ?! Thank you!
    – GA_train
    Jul 10, 2019 at 21:05
  • ls -l presents information about a file. find and stat are 2 other commands that can also present information about a file, just like ls can. The output of ls is not parsable because it's designed for humans to read, not for machines to parse, so just don't do that. In my answer I'm using find to print some info about the files it finds. If you want other info then just add the %whatever strings to the printf to tell find to print that. Just look up the find man page to see what can be printed by using which %-strings.
    – Ed Morton
    Jul 10, 2019 at 21:08
  • 2
    thank you. I was looking at man printf and didn't see much there. However, man find is what I should be looking at. I didn't know p was file name and Ad was day of month util I read more about find. Thanks again!
    – GA_train
    Jul 10, 2019 at 21:22
  • I don't find the outputs to be very accurate. Ex: for -rw-r--r-- 1 user user 35314 Jul 6 19:47 ./95_96xxdata.txt, I get the output of cp -p ./95_96xxdata.txt 09 - it should be 06. Not sure what's going on and there are several examples like this :(
    – GA_train
    Jul 11, 2019 at 15:57
  • 1
    I answered my own question - I should be using %Td instead of %Ad to get the last modified time - that's what I am after, not the last access time. Guess I am learning !
    – GA_train
    Jul 11, 2019 at 16:43
0

Yep, printf is your friend. Use %.2d to 0-pad the number to 2 digits:

find . -mtime -5 -type f -exec ls -ltr {} \; | 
    awk '{printf "cp -p %s %.2d\n", $9, $7}'

To illustrate, I ran the following on a file containing your original output:

$ cat file
cp -p ./18587_96xxdata.txt 10
cp -p ./16947_96xxdata.txt 8
cp -p ./32721_96xxdata.txt 9
cp -p ./32343_96xxdata.txt 9
cp -p ./32984_96xxdata.txt 10
$ awk '{printf "%.2d\n", $NF}' file
10
08
09
09
10

Please note the very good point raised by @edmorton. Parsing ls is very fragile. Ed's solution is far better.

2
  • When I ran your command, I am getting totally different output: cp -p 00 10 cp -p 00 8 cp -p 00 9 cp -p 00 9 cp -p 00 10
    – GA_train
    Jul 10, 2019 at 17:32
  • @GA_t sorry, my bad. I had the fields in the wrong order. But please use Ed's solution instead. This is really not a good approach.
    – terdon
    Jul 10, 2019 at 18:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.