＜bash: find コマンド＞　第一引数に指定したディレクトリ配下から、第二引数以降に一致するファイル・フォルダを除いて削除する

##### 実行は自己責任でお願いします！（ . から始まるファイルも消えます）
```bash:詳細表示版
alias del='eval "set -f" "# $-" && SET="$_" DelEx';
function DelEx () {
    [[ $SET == *f* ]] || set +o noglob
    # 未定義変数チェック
    { 
        set -u;
        local ErrMsg="This function requires arguments.";
        local Usage="Usage: del <path> [<name to exclude> <name to exclude> ...]";
        (: "${1:?"${ErrMsg}${IFS}${Usage}${IFS}"}");
        local ErrLvl=$?;
        [[ $SET == *u* ]] || set +o nounset;
        [[ $ErrLvl -eq 1 ]] && return 1;
    } 
    # 第一引数を絶対パスに変更
    local Path="$1"
    Path="$(realpath -- "$Path")"
    [[ "$Path" == "/" ]] && {
        echo "Cannot execute.";
        return 1;
    }
    # 残りの引数を find で扱える形に調整
    local N=2 Arg=() Escaped Args=()
    while [[ "$N" -le "$#" ]]; do
        Arg[$N]="$N"
        Escaped=$(perl -e "print quotemeta('${!Arg[$N]}');")
        Args+=(! -regex ".*/${Escaped}\(/.*\|\)")
       ((N++))
    done
    # 第一引数が存在するパスであれば削除を実行
    echo "[Summary]"
    echo "Target path: "$'\n'"  '$Path'"
    [[ -d $Path ]] && {
        [[ $1 =~ ^\.+(/+\.*)*$ ]] || { find "$Path" -xdev -maxdepth 0 -delete 2>/dev/null && return; }
        echo "Name to exclude: ";
        local Nest;
        Nest=("${Arg[@]/#/\$\{}");
        eval echo '"  "'"${Nest[@]/%/@Q\}}";
        echo $'\n'"[Verbose]";
        find "$Path" -xdev -depth ! -path "$Path" -regextype findutils-default "${Args[@]}" -print -delete;
        return;
    }
    [[ -f $Path ]] && {
        find "$Path" -xdev -maxdepth 0 -delete;
        return;
    }
    # パスがディレクトリでもファイルでもなかった場合
    echo "failed."
    return 255
}
```
---
```bash:詳細非表示
# bash のワイルドカードによるパス名展開を無効化（/* 対策）
# find による正規表現の解釈も perl で無効化
alias del='eval "set -f" "# $-" && SET="$_" DelEx';

# 正規表現について
# "." :任意の１文字
# "*" :直前の文字に０回以上マッチ(最長一致)
# "|" :OR条件
function DelEx () {
    [[ $SET == *f* ]] || set +o noglob
    # 未定義変数チェック
    { 
        set -u;
        local ErrMsg="This function requires arguments.";
        local Usage="Usage: del <path> [<name to exclude> <name to exclude> ...]";
        (: "${1:?"${ErrMsg}${IFS}${Usage}${IFS}"}");
        local ErrLvl=$?;
        [[ $SET == *u* ]] || set +o nounset;
        [[ $ErrLvl -eq 1 ]] && return 1;
    } 
    # 第一引数を絶対パスに変更
    local Path="$1"
    Path="$(realpath -- "$Path")"
    [[ "$Path" == "/" ]] && {
        echo "Cannot execute.";
        return 1;
    }
    # 残りの引数を find で扱える形に調整
    local N=2 Arg=() Escaped Args=()
    while [[ "$N" -le "$#" ]]; do
        Arg[$N]="$N"
        Escaped=$(perl -e "print quotemeta('${!Arg[$N]}');")
        Args+=(! -regex ".*/${Escaped}\(/.*\|\)")
       ((N++))
    done
    # 第一引数が存在するパスであれば削除を実行
    [[ -d $Path ]] && {
        [[ $1 =~ ^\.+(/+\.*)*$ ]] || { find "$Path" -xdev -maxdepth 0 -delete 2>/dev/null && return; }
        find "$Path" -xdev -depth ! -path "$Path" -regextype findutils-default "${Args[@]}" -delete 2> >(grep -v "Directory not empty" >&2);
        return;
    }
    [[ -f $Path ]] && {
        find "$Path" -xdev -maxdepth 0 -delete;
        return;
    }
    # パスがディレクトリでもファイルでもなかった場合
    return 255
}
```

```bash:bash
# 実行例
mkdir -p ./target/{"delete folder","exclude folder",other_folder}
touch ./target/{'.*[a-z]+',.file1,.file2} ./target/"delete folder"/{file3,file4} ./target/"exclude folder"/{file5,file6} ./target/other_folder/{file7,file8}
tree -a ./target
   ./target
   ├── .*[a-z]+
   ├── .file1
   ├── .file2
   ├── delete folder
   │   ├── file3
   │   └── file4
   ├── exclude folder
   │   ├── file5
   │   └── file6
   └── other_folder
       ├── file7
       └── file8
   3 directories, 9 files
    
set -x
del ./target .*[a-z]+ "exclude folder" file8
set +x
tree -a ./target
   ./target
   ├── .*[a-z]+
   ├── exclude folder
   │   ├── file5
   │   └── file6
   └── other_folder
       └── file8
   2 directories, 4 files



# 実行結果
del ./target .*[a-z]+ "exclude folder" file8
   + set -f
   + DelEx ./target '.*[a-z]+' 'exclude folder' file8
   + set +o noglob
   + set -o nounset
   + ErrMsg='This function requires arguments.'
   + Usage='Usage: del <path> [<name to exclude> <name to exclude> ...]'
   + : ./target
   + Path=./target
   ++ realpath -- ./target
   + Path=/home/$(whoami)/target
   + [[ /home/$(whoami)/target == \/ ]]
   + unset Arg Args
   + N=2
   + Arg=()
   + Args=()
   + [[ 2 -le 4 ]]
   + Arg[$N]=2
   ++ perl -e 'print quotemeta('\''.*[a-z]+'\'');'
   + Escaped='\.\*\[a\-z\]\+'
   + Args+=(! -regex ".*/${Escaped}\(/.*\|\)")
   + (( N++ ))
   + [[ 3 -le 4 ]]
   + Arg[$N]=3
   ++ perl -e 'print quotemeta('\''exclude folder'\'');'
   + Escaped='exclude\ folder'
   + Args+=(! -regex ".*/${Escaped}\(/.*\|\)")
   + (( N++ ))
   + [[ 4 -le 4 ]]
   + Arg[$N]=4
   ++ perl -e 'print quotemeta('\''file8'\'');'
   + Escaped=file8
   + Args+=(! -regex ".*/${Escaped}\(/.*\|\)")
   + (( N++ ))
   + [[ 5 -le 4 ]]
   + [[ -d /home/$(whoami)/target ]]
   + [[ ./target =~ ^\.+$ ]]
   + [[ ./target =~ ^\.+(/+\.*)+$ ]]
   + find /home/$(whoami)/target -xdev -maxdepth 0 -delete
   + find /home/$(whoami)/target -xdev -depth '!' -path /home/$(whoami)/target -regextype findutils-default '!' -regex '.*/\.\*\[a\-z\]\+\(/.*\|\)' '!' -regex '.*/exclude\ folder\(/.*\|\)' '!' -regex '.*/file8\(/.*\|\)' -delete
   ++ grep --color=auto -v 'Directory not empty'
   + return
```