Reputation: 31
I would like to use the stat command inside awk to achieve a modification time in seconds of listed files. I want to keep the output information from stat in a variable and further process inside awk. How to format the command to achieve this objective?
ls -la | awk '{ system("a=$(stat -c %Y $9)"); (further operation on a...) }'
Thanks in advance
Dominik
Upvotes: 1
Views: 3538
Reputation: 395
Small addition to what was said. When having a large number of files:
awk '{ fh="stat -c %Y " $9; fh | getline a; close(fh); stuff_with_a; }'
Otherwise you hit "too many files open".
Upvotes: 1
Reputation: 6239
bash
has no stat
command. bash
is a shell, an application whose primary goal is to run other commands and make them interact together.
stat
is the name of a few different applications, with different syntax whose primary goal is to be an interface to the stat(2)
system call, that is to get and output metadata information about a file.
The one you seem to be referring to seems to be GNU stat
. zsh
is the only shell to my knowledge that has a builtin stat command (with different syntax).
awk
is yet another application, an interpreter for the awk
language, whose primary goal is to do text processing. The awk
language has a system() function that's used to run a shell (sh
, not bash
) command line.
With:
awk '{system("a=$(stat -c %Y $9)")}'
awk
starts a new process that executes a sh
interpreter. That shell sets its own a variable to the output of stat
and then exits. So, that's not useful. What you want is set an awk
variable.
You'll do that with awk
's equivalent of the shell's command subtitution ($(...)
):
awk '{"stat -c %Y " $9 | getline a; ...}'
However, there, awk
's 9th field ends up being expanded and included in the code passed to the shell that interprets that stat...
command line, so it becomes a code injection vulnerability. For instance if $9
is x;reboot
(a perfectly valid file name), the command line becomes stat -c %Y x;reboot
and that will run the reboot
command.
Now, note that GNU ls
can output the unix time by itself.
ls -l --time-style=+%s
Or you could also use GNU
find
to get something that is reliably parseable:
find . ! -name . -prune -printf '%Ts/%s/%p\0' |
while IFS=/ read -d '' -r mtime size name; do
something with "$mtime" "$size" "$name"
done
(here using /
as the delimiter as it's the only character guaranteed not to be found at the end of the paths as output by find
)
find
will also get you sub-second granularity where available with %T@
instead of %Ts
.
Upvotes: 6
Reputation: 426
If you don't need awk, you could always use
find $(pwd) -exec stat \{} --printf="%y\n" \;
Upvotes: 2