実行は自己責任でお願いします!( . から始まるファイルも消えます)
詳細表示版
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 のワイルドカードによるパス名展開を無効化(/* 対策)
# find による正規表現の解釈も perl で無効化
alias del='eval "set -f" "# $-" && SET="$_" DelEx';
# 正規表現について
# "." :任意の1文字
# "*" :直前の文字に0回以上マッチ(最長一致)
# "|" :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
# 実行例
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