0

I am using for loop such as

for j in ls ${folder}/*

to get all subfolders inside my directory ($folder).

But I want only the names of the sub-directories and want to remove directory structure. I use xargs basenme when working with files, but thats not working with directories.

5

You can get a list of all folders in (exactly one level of sub-directories):

find /path/to/dir -maxdepth 1 -mindepth 1 -type d

You can pipe the result into sed command which will leave only the directory name (without the prefix)

find /path/to/dir -maxdepth 1 -mindepth 1 -type d -print0 | sed -z 's!.*/!!' |tr '\0' '\n'

Example:

$ find /var -maxdepth 1 -mindepth 1  -type d 
/var/metrics
/var/lib
/var/local
/var/cache
/var/spool
/var/crash
/var/backups
/var/mail
/var/snap
/var/opt
/var/log
/var/tmp

$ find /var -maxdepth 1 -mindepth 1 -type d -print0 | sed -z 's!.*/!!' |tr '\0' '\n'
metrics
lib
local
cache
spool
crash
backups
mail
snap
opt
log
tmp

Using for loop:

$ for i in $(find /var -maxdepth 1 -mindepth 1 -type d -print0 | sed -z 's!.*/!!' |tr '\0' '\n'); do echo $i; done
metrics
lib
local
cache
spool
crash
backups
mail
snap
opt
log
tmp

for loop re-arranged:

$ for i in $(find /var -maxdepth 1 -mindepth 1 -type d -print0 | sed -z 's!.*/!!' |tr '\0' '\n'); 
    do 
    echo $i
  done
  • 1
    With GNU find (which is what Ubuntu uses) you don't need to use external processing to get the basename - you can use -printf '%f\0' (or -printf '%P\0' to remove just the starting point). Also despite your efforts with \0, looping over a command substitution like for j in $(find ...) will break if any of the results contain whitespace - better to use a null-delimited while loop – steeldriver Sep 20 '18 at 14:05
  • @steeldriver - thanks for your comment! later I'll try to update my answer with the info you add. thanks! – Yaron Sep 20 '18 at 14:55
3

$folder/*/ matches every subdirectory of $folder. Use bash Parameter Expansion to cut out the directory name:

for j in $folder/*/; do
  j=${j%/}
  j=${j##*/}
  …
done

This simply redefines j cutting first the last slash and then everything until the last slash in the string, effectively leaving only the subdirectory name.

1

Better to using find command instead of for-loop.

find "$folder" -mindepth 1 -maxdepth 1 -type d -execdir printf '%s\n' '{}' +

Here we used -execdir which that's changing the directory path where a -directory found, so the {} will containing only the last element when printing which is a directory-name.


Or with GNU find that supports -printf option to formatting.

find "$folder" -mindepth 1 -maxdepth 1 -type d -printf '%f\n'

That -f is returning only the last element with any leading directories removed.


Note: this is limited to list sub-directories only in $folder specified; you can adjust/remove the -maxlength with your requirements.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.