List files with line count and date
Solution 1
Here is something with find
+ wc
+ date
.
find . -maxdepth 1 -exec sh -c '[ -f "$0" ] && \
printf "%6s\t\t%s\t%s\n" "$(wc -l<"$0")" "$(date -r "$0")" "$0"' {} \;
Instead of date -r
one can also use for example stat -c%y
.
The output looks like this:
394 Thu Oct 16 22:38:14 UTC 2014 ./.zshrc
7 Thu Oct 30 11:19:01 UTC 2014 ./tmp.txt
2 Thu Oct 30 06:02:00 UTC 2014 ./tmp2.txt
40 Thu Oct 30 04:16:30 UTC 2014 ./pp.txt
Using this as starting point one can create a function which accepts directory and pattern as parameters:
myls () { find "$1" -maxdepth 1 -name "$2" -exec sh -c '[ -f "$0" ] && \
printf "%6s \t\t%s\t%s\n" "$(wc -l<"$0")" "$(date -r "$0")" "$0"' {} \;; }
After that myls /tmp '*.png'
will list only images from /tmp
(notice single quotes around pattern to prevent shell from expanding a glob operator *
).
Solution 2
The find
-based solutions look the most elegant, but just for fun here are a couple of other ways to attack this.
This one uses sed
& head
to clean up the output of wc
, then uses join
to combine that to the output of stat
, using the file name as the join field.
pat="A*";join -1 2 -2 1 -t ' ' <(wc -l $pat|head -n-1|sed 's/^[ ]*//') <(stat -c '%n %y' $pat) | awk '{printf "%-20s %6s %s %s %s\n",$1,$2,$3,$4,$5}'
And a simpler one that uses paste
, with awk
again tidying up the columns and also checking that the file names match.
pat="A*";paste -d ' ' <(wc -l $pat) <(stat -c '%n %y' $pat) | awk '$2==$3{printf "%6s %s %s %s\n", $1, $4, $5, $2}'
However, if the names don't match (IOW the file lists change while this command is running) then the errors are invisible. But this version reports the errors:
pat="A*";paste -d ' ' <(wc -l $pat) <(stat -c '%n %y' $pat) | awk '$2==$3{printf "%6s %s %s %s\n", $1, $4, $5, $2;next};{print "Error:" $0}'
Of course, that one will print an error message for the final line, but that's easy enough to fix. Or ignore. :)
Related videos on Youtube
John Reid
Updated on September 18, 2022Comments
-
John Reid over 1 year
I want to be able to list files showing the number of lines the each file has and the date. I can happily get the line count using
wc -l *
. Not a problem. I can get the date usingls -l
.Is there a way to combine the two commands to give me a single output in columns?
-
slm over 9 yearsExplain what this is doing and how it works!
-
John Reid over 9 yearsUnfortunately wc dumps a new line which is being left behind.
-
user8973106 over 9 yearsI added tr to remove the "\n"
-
slm over 9 yearsFYI, pay special attn to Jimmij's comment about using
stat -c%y
. You're runningdate
on every file using the former command,date -r
. Otherwise +1, this is a good solution to the Q. -
John Reid over 9 yearsAh I missed it, sorry. It's not working for a list of files now though as it removes all of the line breaks.
-
John Reid over 9 yearsGreat answer. I changed date to
(date -r "$0" -%x)
to give me something to import into a spreadsheet. Exactly what I needed and later I'll have a look at this more in depth. -
Jakob Bennemann over 9 yearsThis seems so unnecessary given the
find
solution proposed above. This solution not only requires three actual commands, but it also uses a file on the system. -
jimmij over 9 years@JohnReid I've changed original post a little, removed unnecessary variables, and added function for patterns. You may want to take a look. @slm you are right that one can do
stat
andwc
on the whole listfind ... {} +
(if this is what you are saying), yes that would be for sure faster, but on the other hand more complicated since one would need to deal with loop over arrays later on (at least as I see it). -
G-Man Says 'Reinstate Monica' over 9 yearsWhy would you choose to use a temporary file when all you need to do is pipe the output of the
awk
intotr
? -
G-Man Says 'Reinstate Monica' over 9 years(1) I realize that the question says "list files", but, if there's only one file in the directory,
wc
will not output a "total" line, and so thehead
will discard the line count of the one existing file. (2) This breaks if filenames contain newlines. (3) This breaks if filenames contain spaces, because you say$file
instead of"$file"
. You should always quote all shell variables references unless you have a good reason not to, and you’re sure you know what you’re doing. -
G-Man Says 'Reinstate Monica' over 9 years@jimmij: Why not say
find -type f
instead of making the shell do the test? -
jimmij over 9 years@G-Man You are right,
-type f
would be simpler.