I'm writing a bash script which needs to, for one step, get a list of directories (variable) in a target directory (which may also contain files), and then expand them out as parameters to a python script.
Example:
/stuff/a dir/
/stuff/b other/
/stuff/c/
And I need to, within a bash script, call:
script.py "a dir/" "b other/" "c/"
or alternately, escaped spaces:
script.py a\ dir/ b\ other/ c/
I need the script to be called exactly once for directory 'stuff'.
Is there a straightforward way to do this kind of thing? I've been googling around and the best I've managed to figure out requires me to know how many directories there are.
Use the ls Command to List Directories in Bash. We use the ls command to list items in the current directory in Bash. However, we can use */ to print directories only since all directories finish in a / with the -d option to assure that only the directories' names are displayed rather than their contents.
To see them in the terminal, you use the "ls" command, which is used to list files and directories. So, when I type "ls" and press "Enter" we see the same folders that we do in the Finder window.
The ls command is used to list files or directories in Linux and other Unix-based operating systems. Just like you navigate in your File explorer or Finder with a GUI, the ls command allows you to list all files or directories in the current directory by default, and further interact with them via the command line.
How can I list directories only in Linux? Linux or UNIX-like system use the ls command to list files and directories. However, ls does not have an option to list only directories. You can use combination of ls command, find command, and grep command to list directory names only.
This is a job for find.
find /stuff -type d -exec script.py {} +
When you use -exec
the curly braces {}
are replaced with the names of the matching files, and +
indicates the end of the command (in case you want to tell find to take additional actions). This is the ideal way to execute a command using find as it will handle file names with unusual characters (such as whitespace) correctly.
find is quite flexible, especially if you have the GNU version typically bundled with Linux distros.
# Don't recurse into subdirectories.
find /stuff -maxdepth 1 -type d -exec script.py {} +
# Pass in a/, b/, c/ instead of /stuff/a/, /stuff/b/, /stuff/c/.
find /stuff -type d -printf '%P\0' | xargs -0 script.py
In the second example notice the careful use of \0
and xargs -0
to use the NUL character to delimit file names. It might seem odd but this allows the command to work even if you do something really weird like use newlines \n
in your directory names.
Alternatively, you could do this using only shell builtins. I don't recommend this, but for educational value, here's how:
# Start with an empty array.
DIRS=()
# For each file in /stuff/...
for FILE in /stuff/*; do
# If the file is a directory add it to the array. ("&&" is shorthand for
# if/then.)
[[ -d $FILE ]] && DIRS+=("$FILE")
# (Normally variable expansions should have double quotes to preserve
# whitespace; thanks to bash magic we don't them inside double brackets.
# [[ ]] has special parsing rules.)
done
# Pass directories to script. The `"${array[@]}"` syntax is an unfortunately
# verbose way of expanding an array into separate strings. The double quotes
# and the `[@]` ensure that whitespace is preserved correctly.
script.py "${DIRS[@]}"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With