GNU/Linux >> Linux の 問題 >  >> Linux

検索から文字列を返す{}を操作します-exec?

ファイルがたくさんある場合に備えて、できるだけ効率的に実行したいと思います。
必要なのは、見つけたすべてのファイルの名前を変更し、それらのサフィックスを削除することです。

例:

[/tmp] $ ls -l
a.log
b.log
c.tmp
[/tmp] $ find /tmp -name "*.log" -type f -exec mv {} {%.*} \;
[/tmp] $ ls -l
a
b
c.tmp

これは機能しません。通常のbash変数の場合${var%.*} varを返したはずです 最後の.まで 。

承認された回答:

シェルを開始して、シェルパラメータ拡張演算子を使用します:

find ~/tmp -name '*.log' -type f -exec sh -c '
  for file do
    mv -i -- "$file" "${file%.*}"
  done' sh {} +

/tmpでは実行したくないことに注意してください または、悪意のあるユーザーが任意の.logの名前を変更できるようにするために、他のユーザーが書き込み可能なディレクトリ ファイルシステム上のファイル¹(またはファイルを任意のディレクトリに移動²)。

いくつかのfind およびmv 実装では、find -execdirを使用できます およびmv -T 安全にするために:

find /tmp -name '*.log' -type f -execdir sh -c '
  for file do
    mv -Ti -- "$file" "${file%.*}"
  done' sh {} +

または、renameを使用します (perlバリアント)rename()を実行するだけです システムコールなので、ファイルを他のファイルシステムやディレクトリに移動しようとしないでください…

find /tmp -name '*.log' -type f -execdir rename 's/\.log$//' {} +

または、perlですべてを実行します :

perl -MFile::Find -le '
  find(
    sub {
      if (/\.log\z/) {
        $old = $_;
        s/\.log\z//;
        rename($old, $_) or warn "rename $old->$_: $!\n"
      }
    }, @ARGV)' ~/tmp

ただし、perlに注意してください のFind::File (GNU findとは異なります )安全なディレクトリトラバーサル³を実行しないため、/tmpで実行したいことではありません。 どちらか。

メモ。

¹攻撃者は/tmp/. /auth.log ファイル、およびfindの間 それを見つけてmv それを移動すると(そしてそのウィンドウは簡単に任意に大きくすることができます)、"/tmp/. "を置き換えます /var/logへのシンボリックリンクを持つディレクトリ 結果として/var/log/auth.log 名前が/var/log/authに変更されます

²さらに悪いことに、攻撃者は/tmp/foo.logを作成する可能性があります 悪意のあるcrontab たとえば、/tmp/foo /etc/cron.dへのシンボリックリンク そのcrontabを移動させます /etc/cron.d 。これがmvのあいまいさです (cpにも適用されます およびln 少なくとも)それは両方とも移動することができます および移動 。 GNU mv -tで修正します ( )および-Tから )オプション。

関連:Sedコマンドで可変日付を使用しますか?

³File::Find chdir("/tmp"); read content; chdir("foo") ...; chdir("bar"); chdir("../..")... 。したがって、誰かが/tmp/foo/barを作成できます ディレクトリを適切なタイミングで、名前を/tmp/barに変更します。 したがって、chdir("../..") /に着陸します 。


Linux
  1. コマンドラインからIPアドレスのジオロケーションを見つける

  2. GitHubリポジトリからコードの行数を検索します

  3. 文字列内のパターンを見つけるためのシェルテスト?

  1. 検索-exec+対検索| Xargs:どちらを選択しますか?

  2. -exec コマンド {} + vs | を検索します。 xargs

  3. adb:adb シェルから PID を見つける

  1. 名前に「abcde」などの特定の文字列が含まれているファイルを見つける方法は?

  2. ファイルのリストを検索から除外する

  3. bash - 部分文字列の文字列インデックス位置を見つける