2

In Unix, is it possible to use one command ONLY to list directories if they contain a sub-directory?

For example, I would like to list the directory name if it contains a sub-directory called "division_A":

/data/data_file/form_100/division_A
/data/data_file/form_101/division_A
/data/data_file/form_102/division_A

The expected result would be:

form_100 
form_101 
form_102

I can only use 2 command lines to realize the goal.

cd /data/data_files
echo `ls -d */division_A 2> /dev/null | sed 's,/division_A,,g'`

So I would like to ask if anyone can use one command to proceed it.

  • 1
    Are you only looking for sub-directories with a specific name or do you want a list of directories that are not empty? – slm Aug 2 '13 at 14:36
  • I would like to list the directory only if a specified sub-directory exists. If the directory does not contain the specified sub-directory, the directory name should not be listed. You can say I am only looking for sub-directories with a specific name and then list its node directory out. Thanks. – Newbiee Aug 2 '13 at 23:24
  • Even the sub-directory is empty, I still want to list its node directory. Once the node-directory contains a specified sub-directory regardless of its volume (i.e. empty or not), list the node directory. Thanks. – Newbiee Aug 2 '13 at 23:30
  • OK, thanks. So from the sound of it there are several solutions that provide this. Are you looking for something beyond that? If not please mark one the answer as the accepted solution so everyone knows your question has been answered to your satisfaction. – slm Aug 3 '13 at 0:00
  • Yes, several solutions can solve my problems and I do not need to take further action beyond that. Thanks for anyone providing suggestion again! – Newbiee Aug 3 '13 at 0:16
2

Using ls is usually not a good idea for parsing through the filesystem. Use find for this type of work.

list of directories not empty

If you want a list of directories that are not empty you can use the following command:

Sample data:

$ tree
.
|-- empty1
|-- empty2
|-- empty3
|-- full1
|   |-- division_A
|   |-- empty1
|   `-- full1
|       `-- afile
|-- full2
|   |-- division_A
|   |-- empty2
|   `-- full2
|       `-- afile
`-- full3
    |-- division_A
    |-- empty3
    `-- full3
        `-- afile

You can then use this command:

$  find . -mindepth 1 -not -empty -type d
./full3
./full3/full3
./full2
./full2/full2
./full1
./full1/full1

This is a list of all the directories that are NOT empty. This output can be cleaned up using awk and uniq if needed.

The above command as POSIX compliant would be:

$ find  . -type d -exec sh -c '[ -n "$(ls -UA "$1/" )" ]' dummy {} \; \
      -print |grep -v '^.$'

List of dirs. that contain dir. division_A

If however you're looking for a list of directories that contain "division_A" you can use this find command to do it:

$ find . -type d -name "division_A" -exec dirname {} \;|sort -u
./full1
./full2
./full3

Here you could use sed to cleanup the output if needed:

$ find . -type d -name "division_A" -exec dirname {} \;| sed 's/\.\///' |sort -u
full1
full2
full3
| improve this answer | |
  • -empty, -mindepth are not POSIX either (only GNU and most recent BSDs). – Stéphane Chazelas Aug 2 '13 at 17:10
  • @StephaneChazelas - does the POSIX version of the command look OK now? I tried to not use any of the switches that aren't. I found a form of that command here: superuser.com/questions/81046/aix-find-non-empty-directories. – slm Aug 2 '13 at 17:51
  • -U and -A options to ls are no POSIX – Stéphane Chazelas Aug 2 '13 at 18:07
  • @StephaneChazelas - starting to feel like the "P" in POSIX stands for "PAIN" 8-). – slm Aug 2 '13 at 18:09
  • Thanks for your reply first. I did not specify the requirement clearly in the question. I would like to search the directory from /data/data_files. After studying your suggestion, I just amended a bit to realize it. COMMAND: find /data/data_file -type d -name "division_A" -exec dirname {} \; | sed 's,/data/data_file/,,g' – Newbiee Aug 3 '13 at 0:02
3

If you have GNU find available, you can use its -printf option to format the output to only print the results' parent directory without having to call other tools like dirname, e.g.:

$ find
.
./data_file
./data_file/form_100
./data_file/form_100/division_A
./data_file/form_101
./data_file/form_101/division_A
./data_file/form_102
./data_file/form_102/division_A

$ find -type d -name 'division_A' -printf "%h\n"
./data_file/form_100
./data_file/form_101
./data_file/form_102
| improve this answer | |
  • If there are multiple subdirectories in each directory, you can use sort -u to remove duplicates. – user26112 Aug 2 '13 at 14:58
  • @EvanTeitelman, under normal conditions, there can't be more than one division_A subdirectory in a given directory. – Stéphane Chazelas Aug 2 '13 at 17:05
  • @StephaneChazelas: Indeed. I did not think that through fully. – user26112 Aug 2 '13 at 17:06
  • Thanks for your reply first. I did not specify the requirement clearly in the question. I would like to search the directory from /data/data_files. After studying your suggestion, I just amended a bit to realize it. COMMAND: find /data/data_file -type d -name 'division_A' -printf "%h\n" | sed 's,/data/data_file/,,g' – Newbiee Aug 2 '13 at 23:59
3

With zsh:

print -rl -- **/division_A(:h:t)
| improve this answer | |
1
for f in ./*/; do [[ -d "$f"division_A ]] && echo "$f"; done

If you want recursiveness:

shopt -s globstar
for f in ./**/*/; do [[ -d "$f"division_A ]] && echo "$f"; done
| improve this answer | |
0

Instead of CD ing to that directory, use this:

echo `ls -d /data/data_files/*/division_A 2> /dev/null | sed 's,/division_A,,g'`
| improve this answer | |

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.