0

find /tmp -type l -exec ls -l出力の $TARGET_NAME 値と正確に一致させるにはどうすればよいですか?

 $ find /tmp -type l -exec ls -l 2>/dev/null {} +
 lrwxrwxrwx 1 root root  24 Mar 18 12:41 /tmp/test/link -> /usr/admin/Collect_tests
 lrwxrwxrwx 1 root root  43 Mar 18 12:41 /tmp/test/link1 -> /usr/admin/Collect_tests/Upload.CM@.www.com
 lrwxrwxrwx 1 root root  68 Mar 18 12:41 /tmp/test/link2 -> /usr/admin/Collect_tests/Upload.CM@.www.com/Upload_Shema@@@.DATA.com
 lrwxrwxrwx 1 root root 100 Mar 18 12:42 /tmp/test/link3 -> /usr/admin/Collect_tests/Upload.CM@.www.com/Upload_Shema@@@.DATA.com/List.files.emails.dummy*Printed
 lrwxrwxrwx 1 root root  92 Mar 18 12:42 /tmp/test/link4 -> /usr/admin/Collect_tests/Upload.CM@.www.com/Upload_Shema@@@.DATA.com/List.files@emails.dummy

値の例

 TARGET_NAME=Upload.CM@.www.com
 TARGET_NAME=Upload_Shema@@@.DATA.com
 TARGET_NAME=List.files.emails.dummy*Printed

Target: print: "link name" と "PATH" (最後のフィールド) は、$TARGET_NAME が最後のフィールドの単語と正確に一致する場合のみ。

例 (正確に一致させたい場合 - while TARGET_NAME =Upload_Shema@@@.DATA.com then):

結果は次のように表示されます

/tmp/test/link2 /usr/admin/Collect_tests/Upload.CM@.www.com/Upload_Shema@@@.DATA.com
/tmp/test/link3 /usr/admin/Collect_tests/Upload.CM@.www.com/Upload_Shema@@@.DATA.com/List.files.emails.dummy*Printed
/tmp/test/link4 /usr/admin/Collect_tests/Upload.CM@.www.com/Upload_Shema@@@.DATA.com/List.files@emails.dummy

いくつかの条件があります:

1) 最後のフィールドのみを一致させる必要がある (ls -l出力から)

      /usr/admin/Collect_tests/Upload.CM@.www.com

2) $TARGET_NAME 値は単語全体と一致する必要があります

完全一致の例 ( while TARGET_NAME=Upload.C​​M@.www.com ):

    /usr/admin/Collect_tests/Upload.CM@.www.com

非完全一致の例:

    /usr/admin/Collect_tests/Upload.CM@.www.c

3) $TARGET_NAME の左側にバックスラッシュ ("/") が存在し、$TARGET_NAME の右側にバックスラッシュまたは文字列の末尾が存在する必要があります。

4) 特殊文字を次のようにエスケープする必要があります: " / " , " @ " . 「 * 」など

5) コードは ksh スクリプトの一部になります (Perl oneliner、AWK、ksh などで実装できます。)

   find /tmp -type l -exec ls -l 2>/dev/null {} + | < Perl one liner .............. >    
4

4 に答える 4

0

これを試してみてください:

#!/bin/bash

while IFS= read -r file; do
    printf "TARGET_NAME=%q\n" "$file"
done < <(find /tmp -type l -printf '%l\n')

結果はバックスラッシュされます。次に例を示します。

TARGET_NAME=/tmp/foo/List.files.emails.dummy\*Printed
于 2013-03-18T13:30:42.650 に答える
0

ターゲットは返される部分と同じかもしれないし、同じでないかもしれないので、2 つの別々の正規表現呼び出しを行うのが最も簡単なようです (これを一般化する必要がある場合にも役立つかもしれません):

perl -ne 'print "$1" if (m#Upload.CM@.www.com# && m#([^/]+)\s*$#);'

つまり、ターゲット フレーズを検索してから、find の最後のコンポーネント (「/」を含まないコンポーネント) を取得します。両方の条件が満たされた場合、括弧内にキャプチャされたテキストを出力します。

特殊文字について: "#" をより伝統的な "/" に置き換える場合は、私が書いた "/" をエスケープする必要があります。それ以外の場合、"@" が問題になることはありません。もちろん、あなたのシステムでそうなった場合は、"\" でエスケープしてください。

于 2013-03-18T13:53:55.477 に答える
0

次のリンクを考えると

$ cd /tmp

$ ls -l link* | sed -e 's/^.*\(link\)/\1/'
link -> /usr/admin/Collect_tests
link1 -> /usr/admin/Collect_tests/Upload.CM@.www.com
link2 -> /usr/admin/Collect_tests/Upload.CM@.www.com/Upload_Shema@@@.DATA.com
link3 -> /usr/admin/Collect_tests/Upload.CM@.www.com/Upload_Shema@@@.DATA.com/List.files.emails.dummy*Printed
link4 -> /usr/admin/Collect_tests/Upload.CM@.www.com/Upload_Shema@@@.DATA.com/List.files.emails.dummy
link5 -> /usr/admin/Collect_tests/Upload.CM@.www.com/

File::Find モジュールを次のように使用します。

$ TARGET_NAME='Upload_Shema@@@.DATA.com' perl -MFile::Find -le 'find sub {
   -l && defined($dst = readlink $_) &&
   index($dst, $ENV{TARGET_NAME}) >= 0 &&
   print "$File::Find::name $dst" }, @ARGV' /tmp
/tmp/link2 /usr/admin/Collect_tests/Upload.CM@.www.com/Upload_Shema@@@.DATA.com
/tmp/link3 /usr/admin/Collect_tests/Upload.CM@.www.com/Upload_Shema@@@.DATA.com/List.files.emails.dummy*Printed
/tmp/link4 /usr/admin/Collect_tests/Upload.CM@.www.com/Upload_Shema@@@.DATA.com/List.files.emails.dummy

それはワンライナーとして本当に扱いにくいです。別のコマンドとして、

#! /usr/bin/env perl

use strict;
use warnings;

use File::Find;

die "Usage: $0 root-dir ..\n" unless @ARGV;
die "$0: TARGET_NAME is not defined\n" unless exists $ENV{TARGET_NAME};

sub print_matching_target_name {
  return unless -l && defined(my $dst = readlink $_);
  print "$File::Find::name $dst\n" if index($dst, $ENV{TARGET_NAME}) >= 0;
}

find \&print_matching_target_name, @ARGV;

出力例:

$ 検索対象
使用法: find-target root-dir ..

$ 検索対象 /tmp
find-target: TARGET_NAME が定義されていません

$ TARGET_NAME=Upload.C​​M@.www.com ./find-target /tmp
/tmp/link2 /usr/admin/Collect_tests/Upload.C​​M@.www.com/Upload_Shema@@@.DATA.com
/tmp/link3 /usr/admin/Collect_tests/Upload.C​​M@.www.com/Upload_Shema@@@.DATA.com/List.files.emails.dummy*印刷済み
/tmp/link4 /usr/admin/Collect_tests/Upload.C​​M@.www.com/Upload_Shema@@@.DATA.com/List.files.emails.dummy
于 2013-03-18T13:08:46.017 に答える
0

最後の質問への回答で述べたように (削除されたため)、ls出力の解析は非常に最適ではありません。readlink代わりに使用できます。

find /tmp -type l -exec \
   perl -e'
      my $TARGET_NAME = shift;
      for (@ARGV) {
         my $p = readlink($_);
         $p =~ m{(?:^|/)\Q$TARGET_NAME\E(?:/|\z)}
            or next;
         print("$_\t$p\n");
      }
   ' "$TARGET_NAME" {} \;

またはより効率的に、

perl -MFile::Find::Rule -e'
   my ($TARGET_NAME, $BASE) = @ARGV;
   for (File::Find::Rule->symlink->in($BASE)) {
      my $p = readlink($_);
      $p =~ m{(?:^|/)\Q$TARGET_NAME\E(?:/|\z)}
         or next;
      print("$_\t$p\n");
   }
' "$TARGET_NAME" /tmp

要求どおり、これは一致します

TARGET_NAME
TARGET_NAME/
TARGET_NAME/x
.../TARGET_NAME
.../TARGET_NAME/
.../TARGET_NAME/x

だがしかし

TARGET_NAMEx/...
.../TARGET_NAMEx
.../TARGET_NAMEx/...
xTARGET_NAME/...
.../xTARGET_NAME
.../xTARGET_NAME/...

注:サポートしている場合は変更find ... -exec ... \;find ... -exec ... +てください。find

于 2013-03-18T22:01:13.817 に答える