Perl 스크립트가 있습니다
$ cat ~/script.pl
sub main {
my ($file) = @_;
<STUFF>
}
}
foreach (@ARGV) {
main($_);
}
디렉토리의 ~/script.pl
모든 파일을 실행하고 싶습니다. 다음 명령을 사용하여 파일 목록을 가져올 수 있습니다.txt
~/foo
.txt
~/foo
$ find ~/foo -type f -name \*.txt
어떻게든 이 명령을 사용하여 이러한 파일을 내 스크립트에 전달할 수 있습니까?
답변1
예, 명령을 사용하여 이를 수행하는 방법에는 여러 가지가 있습니다 find
. 귀하의 상황을 이해하는 데 중요하다고 생각되는 순서대로 몇 가지를 나열하겠습니다.
귀하의 스크립트는 여러 파일 이름 인수를 허용하는 것으로 보이므로
find
이 명령을 사용하여 이를 수행하는 가장 효율적이고 거의 보편적인 방법은 다음과 같습니다.find ~/foo -type f -name \*.txt -exec perl ~/script.pl {} +
이렇게 하면 발견된 파일 이름 인수를 최대한 많이 사용하여 스크립트가 실행됩니다. 모든 파일 이름을 처리해야 하는 경우 스크립트가 여러 번 호출됩니다. 줄
+
끝에 .이것은 가장 독창적이고 다재다능한 방법입니다. 이는
perl
발견된 각 파일에 대해 한 번 호출되므로 귀하의 경우에는 덜 효율적입니다. 이 사용법은 다음에서 유래합니다.유닉스의 초창기.\;
줄 끝에 있는 이스케이프된 세미콜론( )을 확인하세요 (+
위의 반대).find ~/foo -type f -name \*.txt -exec perl ~/script.pl {} \;
이 명령은
-exec ... +
구문이 에 추가되기 전에 파일 이름이나 기타 매개변수 목록으로 작업할 때 효율성을 높이기 위해 고안되었습니다 . 이는 위의 예와 거의 동일합니다.find
xargs
-exec ... +
find ~/foo -type f -name \*.txt -print | xargs perl ~/script.pl
구현에서 이를 지원하는 경우 인수 뿐만 아니라
-print0
옵션도 사용해야 합니다 . 이로 인해 인수 문자열 사이에 널 문자가 인쇄되고 인수가 널 문자 이외의 다른 것으로 분할되는 것을 방지할 수 있습니다. 이는 파일 이름에 공백이나 기타 특수 문자가 포함된 경우 인수가 잘못 분할되는 것을 방지하는 데 도움이 됩니다.find
-0
xargs
find
xargs
xargs
일반적으로 구문을 사용하는 것이
-exec ... +
더 나은 방법입니다. 이렇게find
하면 파일 이름을 스크립트의 인수 목록에 직접 추가하여 프로세스를 제거하고xargs
. 매뉴얼 페이지를xargs
참조하십시오 .xargs
find2perl
또한 동일한 인수를 사용하여 동일한 작업을 수행하는 프로그램을find
인쇄하는 이 명령을 볼 수도 있습니다 . 그런 다음 생성된 코드를 스크립트에perl
통합할 수 있습니다 .perl
아래 생성된 스크립트에서는 대신 함수 호출 옆의 마지막 줄을 수정합니다print
.$ find2perl foo -type f -name \*.txt # /* #[some preamble code removed for brevity] # Traverse desired filesystems File::Find::find({wanted => \&wanted}, 'foo'); exit; sub wanted { my ($dev,$ino,$mode,$nlink,$uid,$gid); (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) && -f _ && /^.*\.txt\z/s && print("$name\n"); }
답변2
다른 답변에서 알 수 있듯이 가능합니다.
나는 대안을 제안하고 싶습니다. 이렇게 하지 말고 내장된 Perl을 사용하십시오. File::Find
기본적으로 동일한 작업을 수행하지만 독립형으로 수행할 수 있습니다.
예를 들어:
#!/usr/bin/env perl
use strict;
use warnings;
use File::Find;
sub process {
return unless -f;
return unless m/\.txt$/; #regex style, not shell glob.
print "Found: Name of $_ as path $File::Find::name in $File::Find::dir\n";
}
find ( \&process, '~/foo' );
~/foo
path()를 하드코딩하거나 에서 가져올 수 있습니다 @ARGV
.
find ( \&process, @ARGV ); #takes as many paths as you specify as args.
답변3
-exec scriptName.sh {} \;
응, 구조 가 있어
귀하의 구체적인 경우에는
find ~/foo -type f -name \*.txt -exec scriptName.sh {} \;
또 다른 방법은 빈 구분 기호를 사용하여 파일을 전달하는 것입니다 xargs
.
이 예는 xargs 매뉴얼에서 직접 가져온 것입니다.
find /tmp -name core -type f -print0 | xargs -0 /bin/rm -f