How do I work recursively through a directory tree and execute a specific command on each file, and output the path, filename, extension, filesize and some other specific text to a single file in bash.
How do I work recursively through a directory tree and execute a specific command on each file, and output the path, filename, extension, filesize and some other specific text to a single file in bash.
While
find
solutions are simple and powerful, I decided to create a more complicated solution, that is based on this interesting function, which I saw few days ago.1. Create executable script file, called
walk
, that is located in/usr/local/bin
to be accessible as shell command:nano
: Shift+Insert for paste; Ctrl+O and Enter for save; Ctrl+X for exit.2. The content of the script
walk
is:3. Explanation:
The main mechanism of the
walk()
function is pretty well described by Zanna in her answer. So I will describe only the new part.Within the
walk()
function I've added this loop:That means for each
$entry
that is a file will be executed the functionfile_specification()
.The function
file_specification()
has two parts. The first part gets data related to the file - name, path, size, etc. The second part output the data in well formatted form. To format the data is used the commandprintf
. And if you want to tweak the script you should read about this command - for example this article.The function
file_specification()
is good place where you can put the specific command that should be execute for each file. Use this format:Or you can save the output of the command as variable, and then
printf
this variable, etc.:Or directly
printf
the output of the command:The section to the begging, called
Colourise the output
, initialise few variables that are used within theprintf
command to colourise the output. More about this you could find here.To the bottom of the scrip is added additional condition that deals with absolute and relative paths.
4. Examples of usage:
To run
walk
for the current directory:To run
walk
for any child directory:To run
walk
for any other directory:To create a text file, based on the
walk
output:To create output file without colour codes (source):
5. Demonstration of usage:
I'm slightly perplexed as to why nobody has posted it yet, but indeed
bash
does have recursive capabilities, if you enableglobstar
option and use**
glob. As such, you can write (almost) purebash
script that uses that recursive globstar like this:Notice that here we use parameter expansion to get the parts of filename we want and we're not relying on external commands except for getting the file size with
du
and cleaning output withawk
.And as it traverses your directory tree, your output should something like this:
Standard rules of script usage apply: make sure it is executable with
chmod +x ./myscript.sh
and run it from current directory via./myscript.sh
or place it in~/bin
and runsource ~/.profile
.You can use
find
to do the jobThis will help you if you just want to list all files with size.
-exec
will allow you to execute custom command or script for each file\;
used to parse files one by one, you can use+;
if you want to concatenate them (means file names).With
find
only.Or, you could use below instead:
If you know how deep the tree is, the easiest way will be to use the wildcard
*
.Write up everything you want to do as a shell script or a function
then run
for i in *; do thing "$i"; done
,for i in */*; do thing "$i"; done
, ... etcWithin your function/script, you can use some simple tests to single out the files you want to work with and do whatever you need to with them.
find
can do this:Have a look at
man find
for other file properties.If you really need the extension, you can add this: