Teekin
Teekin

Reputation: 13289

Unix shell script: Update timestamp on all sub-directories and sub-files, including those with spaces

Here's what I'm trying to achieve.

I have a directory with over 4200 sub-files/sub-directories, all of which need to be set to a certain timestamp.

This is a problem because many of them have whitespaces and other weird characters.

First thing I tried:

touch $(find .)

Won't work because of the spaces. It will update the timestamps on all files and directories that are space-free, but those that are not, do not receive the new timestamp. In addition, as one might expected, it creates files in the root directory corresponding to the elements of filenames with spaces. So if I have a file somewhere named "One Two Three", 'touch' creates the 3 files, "One", "Two" and "Three" in the root. This by itself can be remedied by using -c with 'touch', but of course it still won't update the file with the spacey name.

The second thing I tried was:

for FILENAME in $(find .); do touch -t 201007162310.00 "$FILENAME"; done

But it's the same story.

I've found a couple of results online, but they're all trying to achieve something differently and so suggest ways that won't work for me.

So now I'm lost. Any ideas?

Is it really not possible to make the 'find' command prepend and append each line with a quotation mark or something?

EDIT: This needs to be done via shell script. Using Perl, PHP or any other environment will not help. I could easily do this with anything else than Unix shell scripting, but it has to be in a Unix shell script, preferably not a big one.

Upvotes: 4

Views: 12789

Answers (4)

Roman Cheplyaka
Roman Cheplyaka

Reputation: 38758

find . -exec touch -t 201007162310.00 {} +

This is the simplest and the most robust way to do what you want.

Upvotes: 12

Chance
Chance

Reputation: 2700

If you do

ls -b

the -b will cause the filename to be printed out with the escape character '\' in front of the space.

Update: I tried this

find . | ls -b | xargs touch

and it seemed to work for my little test case.

Upvotes: 0

Beano
Beano

Reputation: 7851

find and xargs can be made to communicate using null terminated strings, so you can do

find . -print0 | xargs -0 touch

This will not do exactly what you want, as there will be a number of invocations of touch causing differing times. Therefore you can use another file to act as a reference timestamp

touch /tmp/ref
find. -print0 | xargs -0 touch -r /tmp/ref

Upvotes: 5

Sjoerd
Sjoerd

Reputation: 75629

A couple of options:

  • Use read, like this find . | while read x; do touch $x; done
  • Use xargs, like this find . -print0 | xargs -0 touch

Upvotes: 1

Related Questions