これは、n + 1個の引数を持つシェルスクリプトを作成することです。ここで、最初の引数はディレクトリ、残りは指定されたファイルで、指定されたファイルを除くすべてのファイルを削除します。
たとえば、電話をかけてみてください。rmexcept . '*.jpg' '*.png'
cd $1
for i in “${@:2}”
do
find . -type f -not -name $i -delete
done
これが私の試みです。ただし、指定された1つのファイル(例rmexcept . '*.jpg'
:)に対してのみ機能します。ファイルが2つ以上の場合(たとえばrmexcept . '*.jpg' '*.png'
)、すべてのファイルが削除されます。 forループを生成したと信じているので、何が間違っているのかわかりません。
答え1
これを試してみてください(コメントはインライン):
#!/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
しかし、もちろん調整できます。
答え2
同じメカニズムランケーオ回答しかし、変数がない最小限の方法で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のコマンドラインと入力の制限。