助け合いフォーラム

LPIC

LPIC Lv1-101(Ver5.0)
問題ID : 35566
問題を開く
カレントディレクトリ以下の全てのファイルについて、それぞれの単語数を表示するコマンドはどれか。

正解

find -type f -exec wc -w {} \;

解説

findは指定したディレクトリ以下からファイルやディレクトリを検索するコマンドです。

findコマンドの書式と主な検索式・アクションは以下のとおりです。

find [検索起点ディレクトリ] [検索式] [アクション]


設問では、「①検索起点をカレントディレクトリとして」それ以下の階層に存在する「②全てのファイル」について、「③それぞれの単語数を表示」するコマンドを求めています。
以下のようにしてコマンドを組み立てます。

①検索起点をカレントディレクトリとして
  検索起点ディレクトリを省略します。
  もしくは検索起点ディレクトリに「.(または./)」または $PWD を指定します。

②全てのファイル
  -typeオプションに f を指定(検索条件のファイルの種類に、通常ファイルを指定)します。

③それぞれの単語数を表示
  各ファイルの単語数を表示するコマンドは「wc(またはwc -w)」です。
   wc [オプション] [ファイル名]
   
   オプションを指定しない場合は行数、単語数、文字(バイト)数の順に実行結果が表示されます。

  findコマンドの検索結果のファイルに対してコマンドを実行するには、「-exec コマンド {} \;」オプションを使用します。
   「{}」は検索結果のファイルに置き換えられます。
   また、「;」は-execで実行するコマンドの終了を意味します。「;」はメタキャラクタのため、シェルによって解釈されないよう「\」でエスケープします。

  したがって、「-exec wc -w {} \;」を指定します。

上記を踏まえて、正解は
・find -type f -exec wc -w {} \;
です。

その他の選択肢は全て、書式は正しいですが設問が求めている動作をしないため、誤りです。
・find -name '*.f' -exec ls -l {} \;
「-exec コマンド {} \;」オプションで「ls -l {}」(検索結果の詳細な一覧を表示する)コマンドを実行していますが、ls -lコマンドでは各ファイルの単語数は表示されません。
(ls -lコマンドで得られる情報…ファイル/ディレクトリ/シンボリックリンクのいずれか、パーミッション、ハードリンクの数、所有ユーザ、所有グループ、ファイルサイズ、最終編集日付、ファイル名)
また、検索条件のファイル名が「0文字以上の文字列」+「.f」に指定されていますので不適切です。
「*」は、「0文字以上の文字列」の意味を持つ、検索時に便利なメタキャラクタです。

・find -name '*.f' -exec mv {} ./wc/ \;
「-exec コマンド {} \;」オプションで「mv {} ./wc/」(カレントディレクトリ直下のwcディレクトリに検索結果を移動する)コマンドを実行しています。
また、検索条件のファイル名が「0文字以上の文字列」+「.f」に指定されていますので不適切です。
「*」は、「0文字以上の文字列」の意味を持つ、検索時に便利なメタキャラクタです。

・find -type f -exec mv {} {}.file \;
「-exec コマンド {} \;」オプションで「mv {} {}.file」(見つかったファイルの名称に.fileを付加する)コマンドを実行しています。

・find -type f -exec chown f {} \; -exec ls {} \;
「-exec コマンド {} \;」オプションを複数指定すると、左から順に実行されます。
「chown f {}」(見つかったファイルの所有者をfユーザに変更)した後で「ls {}」(見つかったファイルの一覧を表示する)コマンドを実行しています。

参考

メタキャラクタは、シェルによって特別に解釈される文字です。

以下は主なメタキャラクタとディレクトリ関連の特殊記号をまとめたものです。


例えばechoコマンドの引数に「*」を指定した場合、シェルは「*」を表示せずカレントディレクトリの内容を表示します。これは、シェルが「*」をメタキャラクタとして特別に認識するためです。

$ echo *
file1 file2

シェルがメタキャラクタを通常の文字として扱う(メタキャラクタをエスケープする)ためには、以下のような方法があります。

・「\」(環境によっては「¥」が表示される)をメタキャラクタの直前に付ける

$ echo \*
*

・「'」でメタキャラクタまたはメタキャラクタを含む文字列を囲む

$ echo '*'
*

・「"」でメタキャラクタまたはメタキャラクタを含む文字列を囲む

$ echo "*"
*

なお、「"」で囲まれた「$」、「`」、「\」、「"」は文字ではなくメタキャラクタとして扱われます。

例)
$ DATE=date
$ echo "$DATE"
date

「"」で囲まれていても「$」はメタキャラクタとして扱われるため、「$DATE」とは表示されず、変数に格納されている値が表示されます。
つまり、「echo "$DATE"」と「echo $DATE」の実行結果は同じです。

例)
$ echo "`date`"
2012年 1月 12日 木曜日 15:00:40 MST

「"」で囲まれていても「`」はメタキャラクタとして扱われるため、「`date`」とは表示されず、dateコマンド(現在の日付と時刻を表示)の実行結果が表示されます。
つまり、「echo "`date`"」と「echo `date`」の実行結果は同じです。

上に戻る

findでのメタキャラクタの説明について

公開日 2023/07/30

この問題の誤答の解説に、以下の記載があります。
find -name '.f' -exec ls -l {} ; ---①
」は、「0文字以上の文字列」の意味を持つ、検索時に便利なメタキャラクタです。---②

参考に以下の記載があります。
メタキャラクタは、シェルによって特別に解釈される文字です。 ---③

①の '*.f' が③のメタキャラクタを含む文字列であるとすると
''で囲まれているため、*はメタキャラクタではなくなってしまう様に思われました。

findコマンド内の '*.f' は、どの様に理解すればよいでしょうか。

例えば ' は、なんらかの理由でメタキャラクタではないが、''で
囲まれた中身は③のメタキャラクタであるということなのでしょうか。

ご存じの方がおられたら、教えて下さい。
宜しくお願いします。

2023/07/30 22:55

findコマンド内の '*.f' は、どの様に理解すればよいでしょうか。

findに渡す検索文字列です。manにもこの文字列はシェルが理解するメタキャラクタによってマッチするものと記載されています。

Base of file name (the path with the leading directories removed) matches shell pattern pattern.

[user@localhost ~]$ man find | grep -A 11 -- '-name pattern'
       -name pattern
              Base of file name (the path with the leading directories removed) matches shell pattern  pat‐
              tern.   Because  the  leading  directories are removed, the file names considered for a match
              with -name will never include a slash, so `-name a/b' will never match anything (you probably
              need  to  use -path instead).  A warning is issued if you try to do this, unless the environ‐
              ment variable POSIXLY_CORRECT is set.  The metacharacters (`*', `?', and `[]') match a `.' at
              the  start  of the base name (this is a change in findutils-4.2.2; see section STANDARDS CON‐
              FORMANCE below).  To ignore a directory and the files under it, use -prune; see an example in
              the  description of -path.  Braces are not recognised as being special, despite the fact that
              some shells including Bash imbue braces with a special meaning in shell patterns.  The  file‐
              name matching is performed with the use of the fnmatch(3) library function.   Don't forget to
              enclose the pattern in quotes in order to protect it from expansion by the shell.


コメント

k kz5835

2023/07/31 01:27

arashi1977様 貴重な情報のご提供、有難うございます。大変参考になりました。 宜しくお願いします。

この返信に対して
コメントを記入できます

この投稿に対して返信しませんか?