1

I'm trying to beat my head against the syntax of this. I'm getting problems with whitespaces and I can't see if there's a better way to do this.

vardir=/home/user
cd $vardir
for i in $(ls "$vardir") ; do
timestamp="$(stat -c %Y $i)"
echo "$i"
echo "$timestamp"

done

Result is similar no matter where I quote and I'm not sure what I'm doing wrong:

stat: cannot stat ‘Temporary’: No such file or directory
Temporary

stat: cannot stat ‘Items’: No such file or directory
Items

My goal is I want to grab the timestamps off of backup directories and touch the current ones to restore the original modified dates.

2

2 Answers 2

6

As other people said before me: Don’t parse the output of ls!

Why not simply:

stat --printf='%y\t%n\n' -- *

If you want to do something with each file name and time stamp, read the output of stat like this:

stat --printf='%y\t%n\0' -- * | \
while IFS=$'\t' read -rd '' timestamp i; do
    echo "filename: ${i}, timestamp: ${timestamp}"
done

No need to spawn a new stat process for every file, which you'll notice as soon as you spawn a few hundred processes for a few hundred files.

For more complicated matches than simple globbing, I recommend find with a suitable -printf option.

Edit: As per the comments to this answer, I found out that OP actually wants to copy the modification time stamps from files of one directory to another. This is what I suggest:

for f in /source/dir/*; do
    touch -c -r "${f}" "/dest/dir/${f##*/}"
done

This takes all entries from /source/dir as time stamp references (-r) for entries of the same file name in /dest/dir without creating new files that don't exist in /dest/dir yet (-c).

5
  • David, thanks. This was clever as hell and did what it needed to as quick as anything. It was trivial to change this to touch -d with a second line for echo in the while loop and this accomplished my goal very simply. Feb 9, 2015 at 23:27
  • 1
    If you want to want to touch a file with the modification time of another, you should use touch -r [REFERENCE FILE] [FILES TO TOUCH] instead of an equivalent of touch -d "$(stat -c %y [REFERENCE FILE])" [FILES TO TOUCH]. Feb 9, 2015 at 23:31
  • Ugh. So I simply could have done touch -r /source/dir/* /dest/dir/* with no script. Feb 9, 2015 at 23:33
  • No, that wouldn't work. touch -r /source/dir/* /dest/dir/* applies the modification time of the first match of /source/dir/* to all the other matches of /source/dir/* and /dest/dir/*. What you want is probably something like my update to the answer. Feb 10, 2015 at 17:18
  • I have a lot to learn! Thanks for your very excellent answers. Feb 10, 2015 at 17:27
4

Do not parse the output of ls, use a glob:

for i in * ; do

Also, quote the variables that might contain spaces:

    timestamp=$(stat -c %y "$i")

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .