web-dev-qa-db-ja.com

rmで複数のディレクトリをクリアする

配列に格納されている複数のディレクトリをクリアしようとしています。これは簡単な例です(私はより多くのディレクトリを持っています)。

#!/bin/bash    

$IMAGES_DIR="/Users/michael/scripts/imagefiles"
$BACKUP_DIR="/Users/michael/scripts/imagebackups"

...

array=( $IMAGES_DIR $BACKUP_DIR )
for i in ${array[@]}
do
    if [ "$(ls -A $i)" ]; then     # check that directory has files in it
        rm "$i/"*                  # remove them 
    fi
done

ディレクトリごとにエラーが発生します。例:

rm:/ Users/michael/scripts/imagefiles/*:そのようなファイルやディレクトリはありません

4
Michael Riordan

単一のコマンドですべてを達成するのはどうですか?

1つのfind呼び出しで、ファイルの存在チェック、グロビング、および削除をキャプチャできます。 GNUバージョンのfindの場合、次のようになります。

for f in "${array[@]}"; do
     find "$f" -type f -delete
done

GNU findがない場合は、次の呼び出しを使用します。

find "$f" -type f -exec rm -f {} +

(ディレクトリ階層全体からファイルをクリアするのではなく、直接の子であるファイルのみをクリアする場合は、-maxdepth 1の前に-type fを追加します。)

待ってください、まだまだあります...

John1024 wisely notes 配列を最初のパラメータとしてfindに渡すことにより、ループを完全に無視できます。

     find "${array[@]}" -type f -delete

これは、1)findが、1回の実行で検索および処理される複数のディレクトリを受け入れるためです2)シェルは、各要素(ディレクトリ)がfindへの個別の位置パラメーターになるように配列を分割します。

5
B Layer

コードを次のように変更します。

_#!/bin/bash    

IMAGES_DIR="/Users/michael/scripts/imagefiles"
BACKUP_DIR="/Users/michael/scripts/imagebackups"

array=( $IMAGES_DIR $BACKUP_DIR )
for i in "${array[@]}"
do
    if [ "$(ls -A "$i")" ]; then     
        rm "${i:?}"/*                 
    fi
done
_

エラー:

  1. 変数割り当ての左側に_$_を配置する
  2. if [ "$(ls -A $i)" ];thenで_$i_を引用しない
  3. これを確認するには、_"${var:?}"_を使用します。_rm "$i/"*_は_/*_に展開されません
0
George Udosen

チェックするために外部プロセスを呼び出さないでください、しかしシェルの内部関数testを使用してください

if test -d "$ i";次に#ディレクトリが存在することを確認します

テストとrmの呼び出しの間に、他のプロセスがすでにディレクトリを消去した可能性があるため、rmは失敗します。スイッチを使用できます-fまたはエラーをリダイレクトします

/ bin/rm "$ i/*" 2>/dev/null#ファイルを削除します

0
Massimo

rm-fオプションを使用すると、ファイルオペランドが存在しない場合でもユーティリティはメッセージを表示しません。また、失敗しても終了しません。

おそらくとは、あなたの場合、1つまたは複数のディレクトリが非表示の名前のファイルまたはディレクトリを除いて空であるため、パターンの最後の*が何でも。 bashシェルオプションを設定することにより、*グロブをdotglobの非表示の名前に一致させることができます。

また、割り当ての変数名に$を付けないでください。Wordの分割とファイル名の生成(グロビング)を回避するために、変数展開を二重引用符で囲む必要があります。変数名は小文字にする必要があります。これにより、環境変数や特別なシェル変数を誤って上書きすることがなくなります。

これらを考慮したコードの代替の定式化。

#!/bin/bash    

shopt -s dotglob

images_dir="/Users/michael/scripts/imagefiles"
backup_dir="/Users/michael/scripts/imagebackups"

dirs=( "$images_dir" "$backup_dir" )

for dir in "${dirs[@]}"; do
    rm -f "$dir"/*
done

上記はディレクトリからすべてのファイルを削除しようとします。ディレクトリにサブディレクトリがある場合、これに関してrmからエラーが発生します。これらも削除したい場合は、rmとともに-rを使用してください。

0
Kusalananda