RafaelGP
RafaelGP

Reputation: 1889

for-loop for every folder in a directory, excluding some of them

Thank you very much in advance for helping!

I have this code in bash:

for d in this_folder/*    
    do    
        plugin=$(basename $d)
        echo $plugin'?'
        read $plugin
    done

Which works like a charm. For every folders inside 'this_folder', echo it as a question and store the input into a variable with the same name.

But now I'd like to exclude some folders, so for example, it will ask for every folder in that directory, ONLY if they are NOT any of the following folders: global, plugins, and css.

Any ideas how can I achieve this?

Thanks!

UPDATE:

This is how the final code looks like:

base="coordfinder|editor_and_options|global|gyro|movecamera|orientation|sa"

> vt_conf.sh
echo "# ========== Base"     >> vt_conf.sh
for d in $orig_include/@($base)
do
    plugin=$(basename $d)
    echo "$plugin=y"         >> vt_conf.sh
done
echo ''                      >> vt_conf.sh
echo "# ========== Optional" >> vt_conf.sh
for d in $orig_include/!($base)
do
    plugin=$(basename $d)
    echo "$plugin=n"         >> vt_conf.sh
done

Upvotes: 12

Views: 18822

Answers (6)

Arthur Zennig
Arthur Zennig

Reputation: 2184

Splitting the path, checking against each foldername to be ignored.
Ignoring folder this way is convenient if you want to increase quantity of folder to be ignored afterwards. (they are here stored in ignoredfolders).
Added comments in the code.
This works fine for me in Ubuntu 20.04.2

#!/bin/bash
shopt -s globstar #necessary for search ./**/*
ignoredfolders=("folder1name" "folder2name")

for i in ./**/*
do
    #pattern for splitting forward slashes into empty spaces
    ARRAY=(${i//\//" "} ); 
    for k in "${ignoredfolders[@]}"; do
        #does path (splitted in ARRAY) contain a foldername ($k) to be ignored? 
        if [[ " ${ARRAY[@]} " =~  "$k"  ]]; then
            #this skips this loop and the outer loop
            continue 2
        fi
    done
    # all ignored folders are ignored, you code sits here...
    #code ...
    #code ...

done

Upvotes: 0

Victoria Stuart
Victoria Stuart

Reputation: 5072

While How to exclude some files from the loop in shell script was marked as a dupe of this Q/A and closed, that Q specifically asked about excluding files in a BASH script, which is exactly what I needed (in a script to check the validity of link fragments (the part after #) in local URLs. Here is my solution.

    for FILE in *
    do
        ## https://linuxize.com/post/how-to-check-if-string-contains-substring-in-bash/
        if [[ "$FILE" == *"cnp_"* ]]
        then
            echo 'cnp_* file found; skipping'
            continue
        fi
        ## rest of script
    done

Output:

    cnp_* file found; skipping

    ----------------------------------------
    FILE: 1 | NAME: linkchecker-test_file1.html
    PATH: /mnt/Vancouver/domains/buriedtruth.com/linkchecker-tests/linkchecker-test_file1.html

     RAW LINE: #bookmark1
    FULL PATH: /mnt/Vancouver/domains/buriedtruth.com/linkchecker-tests/linkchecker-test_file1.html#bookmark1
         LINK: /mnt/Vancouver/domains/buriedtruth.com/linkchecker-tests/linkchecker-test_file1.html
     FRAGMENT: bookmark1
       STATUS: OK
    ...

My test directory contained 3 files, with one that I wanted to exclude (web scrape of an old website: an index with with tons of deprecated link fragments).

[victoria@victoria link_fragment_tester]$ tree
.
├── cnp_members-index.html
├── linkchecker-test_file1.html -> /mnt/Vancouver/domains/buriedtruth.com/linkchecker-tests/linkchecker-test_file1.html
└── linkchecker-test_file2.html -> /mnt/Vancouver/domains/buriedtruth.com/linkchecker-tests/linkchecker-test_file2.html

0 directories, 3 files
[victoria@victoria link_fragment_tester]$ 

Upvotes: 0

Thor
Thor

Reputation: 47099

If you have a recent version of bash, you can use extended globs (shopt -s extglob):

shopt -s extglob

for d in this_folder/!(global|plugins|css)/   
do    
    plugin=$(basename "$d")
    echo $plugin'?'
    read $plugin
done

Upvotes: 18

execjosh
execjosh

Reputation: 714

You could use find and awk to build the list of directories and then store the result in a variable. Something along the lines of this (untested):

dirs=$(find this_folder -maxdepth 1 -type d -printf "%f\n" | awk '!match($0,/^(global|plugins|css)$/)')
for d in $dirs; do
    # ...
done

Update 2019-05-16:

while read -r d; do
    # ...
done < <(gfind  -maxdepth 1 -type d -printf "%f\n" | awk '!match($0,/^(global|plugins|css)$/)')

Upvotes: 0

askmish
askmish

Reputation: 6674

If you meant to exclude only the directories named global, css, plugins. This might not be an elegant solution but will do what you want.

for d in this_folder/*    
do  
    flag=1
    #scan through the path if it contains that string
    for i in "/css/" "/plugins/" "/global/"
    do

    if [[ $( echo "$d"|grep "$i" ) && $? -eq 0 ]]
    then
      flag=0;break;
    fi
    done

    #Only if the directory path does NOT contain those strings proceed
    if [[ $flag -eq 0 ]]
    then
    plugin=$(basename $d)
    echo $plugin'?'
    read $plugin
    fi


done

Upvotes: 1

choroba
choroba

Reputation: 241808

You can use continue to skip one iteration of the loop:

for d in this_folder/*    
    do    
        plugin=$(basename $d)
        [[ $plugin =~ ^(global|plugins|css)$ ]] && continue
        echo $plugin'?'
        read $plugin
    done

Upvotes: 11

Related Questions