zshで複数のディレクトリを表すためにワイルドカード文字で 'rm'を使用するときに空のディレクトリを無視する方法は?

zshで複数のディレクトリを表すためにワイルドカード文字で 'rm'を使用するときに空のディレクトリを無視する方法は?

2つ以上のサブディレクトリ内のすべてのファイルを削除しようとしていますが、zshディレクトリが空の場合、次のディレクトリは無視され、ファイルは保持されます。

例:

$ mkdir dir1
$ mkdir dir2
$ touch dir2/blah

# avoid the zsh safety prompt; this may not be necessary for this
# example, just for ease of use here
$ setopt rm_star_silent
$ rm -r dir1/* dir2/*
zsh: no matches found: dir1/*
$ ls dir2
blah

rmBashでは、すでに空のディレクトリが進行を中断することなくdir2削除さdir2/blahれます。

この関数とは何ですか? のように動作させるzsh方法はありますか?rmbash

答え1

bashとは異なり、zshデフォルトではファイル名生成パターンと一致するものがない場合はエラーが報告されます。この動作は、全体的に、またはモードごとに変更できます。

NULL_GLOBグローバルな不一致パターンによるエラーメッセージを防ぐには、次のいずれかのオプションを設定できますCSH_NULL_GLOB

  • setopt nullglob
    

    パターンに一致するものがない場合は、パラメータリストから削除されます。エラーメッセージは印刷されません。あなたの例では

    rm dir1/* dir2/*
    

    ただ拡張されます

    rm dir2/blah
    
  • setopt cshnullglob
    

    また、一致しないパターンを削除し、一致するパターンがない場合はエラーメッセージを出力しません。

単一パターンのエラーメッセージを回避するには、このパターンに対してオプションが有効になっているかのNように動作するglob修飾子を使用できます。NULL_GLOB

rm dir1/*(N) dir2/*(N)

これは次のように拡張される予定です。

rm dir2/blah

答え2

最善の方法は、2つのディレクトリのファイルと一致する単一のグローブにすることです。

rm (dir1|dir2)/*

これにより、ファイルが見つからない場合でもコマンドは実行されません。

ただしdir1dir2含めることはできませんのでご注意ください/

このような場合は、次のことができます。

files=(foo/bar/*(N) bar/baz/*(N))
if ((#files)); then
  rm $files
else
  echo >&2 No matching file
fi

または、cshnullglobcshまたはBourne shの以前の動作を取得するために使用されます。これは、bash一致しないグローバルオブジェクトがコマンドに渡される偽(IMO)動作に戻るよりも優れています。次のことができます。

set +o nomatch

答え3

良い説明はここにあります。

https://superuser.com/questions/584249/using-wildcards-in-commands-with-zsh

主な点は次のとおりです。

By default, ZSH will generate the filenames and throw an error before executing the command if it founds no matches.

空のディレクトリでは一致が生成されないため、エラーが発生します。答えが示すように、次のことができます。

  1. パラメータを引用符で囲む(例rm -r "dir1/*" "dir2/*":)
  2. unsetopt nomatchファイルに設定する.zshrc
  3. コマンドに環境変数を使用できますnoglob(例noglob rm -r dir1/* dir2/*:)

関連情報