You can call the awk
directly at the exit of find
, without needing the exec
:
find ./ | awk -F"/" '{print $2}'
Only that find ./
also includes the current directory, which means that it also returns ./
in its results. And by passing this to the awk
, it ends up printing a blank line (since in this case there is nothing after the bar).
If you want, you can get around it with a if
:
find ./ | awk -F"/" '{if ($2) { print $2 } else { print $1 } }'
Thus, the current directory (which the find
returns as ./
) will be printed as .
, and other directories will be printed normally.
But this solution still generates a lot of repetition. If you have multiple files in the same directory, for example, the name of this directory will be printed several times.
You can eliminate repetitions using sort
(to sort the results) and then with uniq
(that eliminates consecutive lines that are equal):
find ./ | awk -F"/" '{if ($2) { print $2 } else { print $1 } }' |sort |uniq
Finally, you can use the option -c
, which causes the uniq
return the amount of occurrences for each line:
find ./ | awk -F"/" '{if ($2) { print $2 } else { print $1 } }' |sort |uniq -c
Just remember that this command will also return the files that are in the current directory. If you only want the directories, use find ./ -type d
.
Already for your complete command, I find it easier to make one for
in the results of find
, then you can execute the commands you want:
for dir in $(find ./ -regex '\./.*_.*\.\(doc\|docx\|md\|xls\)$' | awk -F"/" '{if ($2) { print $2 } else { print $1 } }'|sort|uniq )
do
status=$(stat -c "%.10w;%.10y;$(dirname "$dir");$(basename "$dir")" "$dir")
if{something}
etc....
done
With each iteration of for
, the variable $dir
will be the name of one of the directories found. Inside the for
it is easier to execute as many commands as you want, without having to put $()
within another, join with Pipes, etc. I believe this makes it simpler and clearer.
Although in the example above, how are you using dirname
and basename
, nor would you need the awk
after the find
. But anyway, using a for
in the results of find
allows you to put as many commands as you want, and I find it easier than the way you are trying. The -exec
I usually use when it’s to execute a single simple command, for more complex things I prefer the for
even.
If you want to use the awk
within the for
, in accordance with his last comment:
for dir in $(find ./ -regex '\./.*_.*\.\(doc\|docx\|md\|xls\)$'
do
status=$(stat -c "%.10w;%.10y;$(dirname $dir | awk -F"/" '{if ($2) { print $2 } else { print $1 } }');$(basename "$dir")" "$dir")
echo $status
done
If any of the files/directories have space in the name, just set the variable IFS
before the for
:
IFS=$'\n'
for dir ...
With that, the for
considers line breaks (and no longer space) as separator from your records, treating file names and directories with spaces as if they were one thing.
To restore the original value of the variable, I suggest saving it before the change:
OLDIFS=$IFS
IFS=$'\n'
for dir ....
....
IFS=$OLDIFS
your scripts are confused...show a concrete example...do as I did in my reply: show a listing of directories and files, and the lines you want as a result
– zentrunix