0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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

Last updated at Posted at 2024-12-29
実行は自己責任でお願いします!( . から始まるファイルも消えます)
bash
# bash のワイルドカードによるパス名展開を無効化(/* 対策)
# find による正規表現の解釈も perl で無効化
alias del='set -f && DelEx'

# 正規表現について
# "." :任意の1文字
# "*" :直前の文字に0回以上マッチ(最長一致)
# "|" :OR条件
function DelEx () {
    set +o noglob
    set -o nounset
    ErrMsg="This function requires arguments."
    Usage="Usage: del <path> [<name to exclude> <name to exclude> ...]"
    ! (: ${1:?"${ErrMsg}${IFS}${Usage}${IFS}"}) && return 1
    Path="$1"
    Path="$(realpath -- "$Path")"
    [[ "$Path" == "/" ]] && {
        echo "Cannot execute.";
        return 1;
    }
    unset Arg Args
    N=2; Arg=(); 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
# 実行例
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
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?