`..`ではなくドットファイルに展開されるシェルファイル名パターン?


13

最近、シェルパターンが予期せぬ方法で拡大したために、ちょっとした事故が起こりました。/rootディレクトリ内の多数のドットファイルの所有者を変更したかったので、

chown -R root .*

当然のことながら、.*に拡大し..ているが、災害のビットでした。

私はbashこの動作でいくつかのシェルオプションを調整することで変更できることを知っています、デフォルト設定では、ディレクトリ内のすべてのドットファイルに展開されますが、では.あり..ませんか?

回答:


20

Bash、ksh、およびzshにはより良いソリューションがありますが、この回答ではPOSIXシェルを想定しています。

パターン.[!.]*は、ドットで始まり、その後に非ドット文字が続くすべてのファイルに一致します。([^.]一部のシェルではサポートされていますが、すべてではないことに注意してください[!.]。ワイルドカードパターンの文字セット補完の移植可能な構文はです。)したがって、.およびを除外し..ます。このパターン..?*は、2つのドットで始まり、単なるドットではないファイルを処理します..

chown -R root .[!.]* ..?*

これは、すべてのファイルに一致するように設定された古典的なパターンです。

* .[!.]* ..?*

このアプローチの制限は、パターンの1つが何にも一致しない場合、コマンドに渡されることです。あなたは除いて、ディレクトリ内のすべてのファイルを一致させたいスクリプトでは...、それらすべて面倒なのいくつかのソリューションは、あります。

  • 使用* .*するすべてのエントリを列挙し、除外する...ループインチ パターンの一方または両方が何にも一致しない可能性があるため、ループは各ファイルの存在を確認する必要があります。他の基準でフィルタリングする機会があります。たとえば、-hぶら下がっているシンボリックリンクをスキップする場合は、テストを削除します。

    for x in * .*; do
      case $x in .|..) continue;; esac
      [ -e "$x" ] || [ -h "$x" ] || continue
      somecommand "$x"
    done
  • コマンドが1回だけ実行される、より複雑なバリアント。位置パラメータは上書きされることに注意してください(POSIXシェルには配列がありません)。これが問題になる場合は、これを別の関数に入れてください。

    set --
    for x in * .[!.]* ..?*; do
      case $x in .|..) continue;; esac
      [ -e "$x" ] || [ -h "$x" ] || continue
      set -- "$@" "$x"
    done
    somecommand "$@"
  • * .[!.]* ..?*三連祭壇画を使用してください。繰り返しますが、1つ以上のパターンが何にも一致しない可能性があるため、既存のファイル(ダングリングシンボリックリンクを含む)を確認する必要があります。

    for x in * .[!.]* ..?*; do
      [ -e "$x" ] || [ -h "$x" ] || continue
      somecommand "$x"
    done
  • * .[!.]* ..?*tryptichを使用し、パターンに一致する場合にのみコマンドを1回実行します。これは、コマンドを1回だけ実行します。位置パラメータは破壊されていることに注意してください(POSIXシェルには配列がありません)。これが問題になる場合は、これを別の関数に入れてください。

    set -- *
    [ -e "$1" ] || [ -h "$1" ] || shift
    set -- .[!.]* "$@"
    [ -e "$1" ] || [ -h "$1" ] || shift
    set -- ..?* "$@"
    [ -e "$1" ] || [ -h "$1" ] || shift
    somecommand "$@"
  • を使用しfindます。GNUまたはBSDのfindでは、オプション-mindepthとを使用して再帰を簡単に回避できます-maxdepth。POSIX findを使用すると、少し複雑になりますが、実行できます。この形式には、ファイルごとに1回ではなく1回だけコマンドを簡単に実行できるという利点があります(ただし、これは保証されません。結果のコマンドが長すぎる場合、コマンドは複数のバッチで実行されます)。

    find . -name . -o -exec somecommand {} + -o -type d -prune

6

これは、すべてのファイル名に少なくとも3文字(ドットを含む)が含まれている場合に機能します。

chown -R root .??*

より堅牢なソリューションのために、次を使用できますfind

find . -maxdepth 1 -name '.*' -exec chown -R root {} \;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.