Search code examples
linuxbashshellfindsh

Bash command to list names of specific directories and subdirectories on Linux


I need a bash command that searches the directory "rawdata" for all subdirectories with names starting with "AB", searches all these for the subdirectory "demo" and within all "demo" directories all subdirectories with a name consisting of just numbers. From all these I need the name of the file that has ".txt" as an extension. The command always has to look just one depth and not search deeper... I tried to write all the found filenames in "test.txt" but my code didn't work right.

My approach:

find rawdata/AB* -type d -name 'demo' -exec find {} -mindepth 1 -maxdepth 1 -type d -regex '.*/[0-9]+' -exec find {} -mindepth 1 -maxdepth 1 -type f -name "*.txt" {} \; | awk -F/ '{print $NF}' > test.txt

I got error messages like this:

‘rawdata/AB.../q.../A.../demultiplexed’: No such file or directory

which for me is a proof that it does not first search for demo, because it took the subdirectory q... Further on it didn't take a folder with a number as name!

A correct path should look like this: ‘rawdata/AB.../demo/123/hereAndJustInThisLevelHereIsTheSearchedFile.txt’ So on every first directory level there must be the order "rawdata", on the second level it should just check the directories whose names start with "AB", in the third level there is just one "demo" and it should check just this and in the fourth level it must check just all directories that have a number as folder name!

I already tried some other similar code versions but none of them gave me the right result.


Solution

  • This Shellcheck-clean code demonstrates a possible way to do what you want with pure POSIX shell:

    #! /bin/sh -
    
    for txtfile in rawdata/AB*/demo/*/*.txt; do
        case $txtfile in
            rawdata/AB*/demo/*[!0-9]*/*.txt) : ;;
            *) [ -f "$txtfile" ] && printf '%s\n' "${txtfile##*/}" ;;
        esac
    done
    
    • See the Pattern Matching Notation section of the POSIX Shell Command Language document for an explanation of the rawdata/AB*/demo/*/*.txt and rawdata/AB*/demo/*[!0-9]*/*.txt patterns.
    • rawdata/AB*/demo/*[!0-9]*/*.txt) : ;; causes files in level 3 subdirectories that contain non-numeric characters to be skipped.
    • See the Parameter Expansion section of the POSIX Shell Command Language document for an explanation of ${txtfile##*/}.
    • This code works with Bash, but if it will always be run with Bash then it would be better (shorter, clearer) to use the extglob feature to match numeric directory names.