3

I am looking at the touch command line utility (on Linux), and from the examples I found in tutorials, I see how one can bump the access or modification timestamp to a specified time, the current time, or to a reference file.

However, I would like to do the following: The relative age of my files (relative to each other) has information valuable to me, and I'd rather not lose that. But I need each file in (recursive) folders look a few months younger than they are. So each file could refer to itself, bump the time, but apply this to each file in a tree of folders. What is a good way to do this?

#!/bin/bash
FILES=$(find $HIGHEST_FOLDER -type f -name *.*)
for f in $FILES
do
  touch -ram f -F 7776000 f
  # bumping access and modification timestamps by 3 months?
done

Or am I better off using find -exec as suggested in this answer? (There are many files in these folders.) How could that work?

  • Are you using Linux? If not, which OS? The touch utility behaves differently on different *nixes. – terdon Jan 30 '15 at 14:40
  • Is "younger" meaning you want a file that was created in January 2015 to be updated forwards to April 2015, or backwards to October 2014? – roaima Jan 30 '15 at 18:43
  • Forward, from September to December, say. – László Jan 30 '15 at 18:44
2

Assuming your are on a Linux system, or at least that you have GNU touch and GNU date, you can do (in bash; zsh is the same but does not need the shopt globstar):

$ shopt globstar
$ for f in **; do 
    touch -d "$(date -d "$(stat -c '%y' "$f") +3 months")" "$f"
  done

That, however, will ignore hidden files. To match those as well, run shopt -s dotglob before the above commands.

Explanation

  • shopt -s globstar : This sets bash's globstar option which means that ** will match all files and zero or more directories and subdirectories.
  • shopt -s dotglob: makes * (and **) also match files whose names begins with a ..
  • for f in **; do ...; done : iterate over all files and directories, saving them as $f.
  • stat -c '%y' "$f" : this is the current time stamp of the current file or directory.
  • date -d $(...) +3 months : print the date that is three months after the given string (in this case, that string is the output of the stat command on $f).

All together, the above will find the modification date of each file or directory in the current folder (including all subdirectories) and set its date three months after whatever it is now.

  • The explanation refers to shopt lines which are not in the answer. What did you mean? – László Mar 1 '15 at 21:13
  • 1
    @László not sure what you mean. Both globstar and dotglob are mentioned in the answer. – terdon Mar 2 '15 at 10:39
  • The code has nothing about globstar or dotglob. – László Mar 2 '15 at 15:11
  • 1
    @László look again. Use your browser's search function if you must :) I am using globstar in the example and mention dotglob just under it. – terdon Mar 2 '15 at 15:23
1

From the description of the problem I believe you are looking for the tool which can get time of last file modification and then add 3 months to it. You can do it with stat + touch + some shell arithmetic evaluation. For example to add 90 days to file timestamp you can write

touch -d "@$(( $(stat -c '%Y' file) + 90*24*3600 ))" file

Then just loop over all files you need to.

1

I would use the -exec of find - a oneliner.

find $HIGHEST_FOLDER -type f -name '*.*' -exec touch -d "$(date -d "$(stat -c '%y' {}) +3 months")" {} \;

Quote *.*, otherwise find will take filenames from the current directory and fail.

Finally, you MUST specify \;, backslash followed by semi-colon, -exec mandates this. the {} is the current file find found.

There is no -F switch to GNU touch, so your example does not work. There are also multiple syntax issues:

In your for loop above, you need to change f to $f:

touch [...] $f

Otherwise it will look for a file named f in the current directory and change its date x times, where x is the number of files under $HIGHEST_FOLDER.

If you stick to sub shell ($(...) before your loop), you must make sure that $HIGHEST_FOLDER is set in the sub shell.

  • 1
    What system is this on? Neither GNU coreutils nor FreeBSD supports touch -F to make a relative change to a timestamp. The whole point of the question is how to make that change. – Gilles Jan 31 '15 at 21:54
  • 1
    Indeed, I meant to fix the op's syntax ... I should have probably looked up the man page for touch; I was assuming op had already done that. Editing answer with find variant which I think is better (it includes dot files). – thecarpy Feb 2 '15 at 7:00
  • @thecarpy I just tried this. I am getting a stat: cannot stat `{}': No such file or directory message. – László Mar 1 '15 at 21:03

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.