タスクは、n + 1個の引数を使用してシェルスクリプトを作成することです。最初の引数はディレクトリで、残りは指定されたファイルであり、指定されたファイルを除くすべてのファイルを削除します。
例えば。 rmexcept . '*.jpg' '*.png'
を呼び出す
cd $1
for i in “${@:2}”
do
find . -type f -not -name $i -delete
done
これが私の試みです。ただし、指定された1つのファイル(rmexcept . '*.jpg'
など)でのみ機能します。複数のファイルがある場合(例:rmexcept . '*.jpg' '*.png'
)、すべてのファイルが削除されます。 forループを作成したと思うので、何がうまくいかなかったのか理解できません。
これを試してください(インラインコメント):
#!/bin/bash
set -f # Prevent e.g. *.txt from being expanded here
dir=$1 # Get the target directory and
shift # remove from list of args
cmd="find $dir -type f"
while (( "$#" )) # While there are more arguments left
do
cmd="$cmd -not -name $1" # add to not match
shift # and remove from list of arguments
done
cmd="$cmd -exec rm -i {} ;" # finally execute rm on the remaining matches
echo $cmd # Print the final find command
$cmd # And execute it
追加した -i
からrm
に、各ファイルを削除する前に確認するようにします。もちろん、それを微調整することはできます。
laenkeioの答え と同じメカニズムですが、より最小限の変数なしとして[〜#〜] posix [〜#〜]シェル関数:
rmexcept(){ find "$1" $(shift; printf " -not -name %s" ${@}) -exec rm '{}' \; ;}
printf
またはfor
ループの代わりに、シェルのwhile
コマンドが主な作業を行います。
bash
シェルを使用すると、shift
をパラメーター展開で置き換えることができます。
rmexcept(){ find "$1" $(printf " -not -name %s" ${@:2}) -exec rm '{}' \; ;}
結果のfind
またはrm
コマンドがgetconf ARG_MAX
によって返される数よりも長い場合、どちらの関数もジョブを終了しないことに注意してください。参照:Bashコマンドラインと入力制限。