"linux run find on find"에 대한 웹 검색을 수행했지만 관련 결과가 나오지 않았습니다. 찾기에서 파일 목록을 작성한 다음 해당 목록에서 찾기를 다시 실행하고 싶습니다.
몇 가지 "어리석은" 버그를 수정한 후 명령줄 작업 경험이 거의 없었기 때문에 최종 명령은 다음과 같았습니다.
find "path1" -size 0 -printf "%f\0" | xargs -0 --max-args=1 --verbose find "path2" -exec ls -l {} \\\; -name
As --verbose
, 명령이 다음과 같이 실행되는 것을 봅니다.
find path -exec ls -l {} \; -name foundfilename
그리고 출력 missing argument to exec
.
결과 명령 build를 직접 실행 하면 xargs
(어떤 이유로 큰따옴표 xargs --verbose를 추가하면 출력이 누락되지만 실제로는 find에 공백이 포함된 경로에 문제가 없으므로 실제로 작동합니다.)
find "path" -exec ls -l {} \; -name foundfilename
출력은 다음과 같습니다 path
.
- xargs와 직접 실행의 결과가 다른 이유는 무엇입니까
find
? - 외모는
-exec
앞에 올 수 없습니다-name
. 맞나요? - 마지막으로 요점:
find
결과를 서로 올바르게 실행하는 방법은 무엇입니까find
?
시스템: 리눅스 민트 19.2
두 번째 질문을 명확히하기 위해 의견 뒤에 추가되었습니다.
내가 달리면
find "path" -name foundfilename -exec ls -l {} \;
예상대로 발견되어 나열된 여러 파일의 출력 ls
, 즉 두 번째 질문을 얻습니다.
.1
2
/media/ramdrive
marina@tpx:~$ find /media/ramdrive -exec ls {} \; -name 1
1 2
/media/ramdrive/2
/media/ramdrive/1
marina@tpx:~$ find /media/ramdrive -name 1 -exec ls {} \;
/media/ramdrive/1
그 남자는 다음을 발견했습니다.
-명령을 실행합니다. 명령을 실행합니다. 상태 0이 반환되면 true입니다. find에 대한 다음 인수는 모두
;' is encountered. The string
{}'로 구성된 인수가 일부 버전의 find에서와 같이 별도의 인수가 아닌 명령에 대한 인수에 나타나는 현재 파일 이름으로 대체될 때 까지 명령에 대한 인수로 처리됩니다 . 두 구성 모두 셸 확장으로부터 보호하기 위해 이스케이프('' 사용)하거나 인용해야 할 수 있습니다. -exec 옵션 사용에 대한 예는 예 섹션을 참조하세요. 일치하는 각 파일에 대해 지정된 명령이 한 번 실행됩니다. 이 명령은 시작 디렉터리에서 실행됩니다. -exec 작업을 사용할 때 피할 수 없는 보안 문제가 있으므로 -execdir 옵션을 사용해야 합니다.
-exec
왜 일치 옵션 이전에 있을 수 없는지 이해가 되지 않습니다 .
실제로 "별도의 인수뿐만 아니라 명령 인수의 어느 곳에나 나타납니다"가 무엇을 의미하는지 이해하지 못합니다.
두 가지를 더 추가합니다.
그래도 해결책을 찾았습니다.
find "path1" -size 0 -printf "%f\0" | xargs -0 --max-args=1 --verbose find "path2" -name | xargs ls -l
그러나 find의 기본 인쇄는 결과를 인용하지 않으므로 공백이 있는 경로에서는 실패합니다. 따옴표를 추가하는 유틸리티가 있나요?
답변1
왜
xargs
직접find
조작과 결과가 다른가요?
때를유형 find path -exec ls -l {} \; -name foundfilename
쉘에서는 쉘을 \;
" ;
명령에 전달됨"으로 발음합니다. 그냥 ;
입력하면 명령 구분 기호가 됩니다. 백슬래시는 쉘에 의해 "먹히고" 이에 따라 동작이 변경됩니다 ;
.
언제 xargs
말했어?달리다 find path -exec ls -l {} \; -name foundfilename
, 백슬래시를 제거하기 위해 실제로 셸 없이 명령에 전달됩니다 \;
(즉, 에 전달됨 ). find
따라서 \;
오류는 다음과 같습니다. or 을 -exec
기대하면 둘 중 하나도 얻지 못하므로 "exec에 대한 인수가 누락되었습니다".;
+
외모는
-exec
앞에 올 수 없습니다-name
. 맞나요?
잘못된. 그것은 할 수 있습니다. 아닐 수도 있습니다. 원하는 작업에 따라 다릅니다. 두 명령의 서로 다른 결과는 쉽게 설명됩니다. 이 두 명령은 다음과 같습니다.
find /media/ramdrive -exec ls {} \; -name 1
find /media/ramdrive -name 1 -exec ls {} \;
중요한 사실:
-exec
그것은 또한 테스트이다. 내부 명령이 반환되는 경우에만 성공합니다0
.-o
테스트는 ( 논리적 OR) 또는-a
(논리적 AND) 연산자로 연결됩니다 .-a
귀하의 경우와 같이 연산자가 누락되었다고 가정하십시오.-test1 -o -test2
또는 를 사용-test1 -a -test2
하고-test1
먼저 테스트하세요. 결과가 그것만으로 결정되면-test1
실행-test2
되지 않습니다. 특히, 이는-test1 -a -test2
성공할 경우에만 실행됨을 의미합니다(우리는 이미 결과를 알고 있으므로 실패할 경우에는 필요하지 않습니다: 실패).test2
-test1
-test2
전체 테스트가 -exec ls {} \; -name 1
(예: -exec ls {} \; -a -name 1
) 인 경우 -exec
각 후보를 테스트하세요. 이것은 이미 표준 출력으로 무언가를 인쇄합니다. 성공한 각 후보에 대해 ls
다른 테스트가 실행되지만 다른 테스트에서는 아무것도 인쇄되지 않고 추가 테스트/작업이 없기 때문에 중요하지 않습니다(기본값은 -print
이전에 의해 억제됨 -exec
).
전체 테스트가 -name 1 -exec ls {} \;
(예: -name 1 -a -exec ls {} \;
) 인 경우 -name
각 후보를 테스트하세요. 테스트는 아무 것도 인쇄하지 않지만 결과에 따라 -exec
실행 여부가 결정됩니다. 따라서 ls
iff를 성공적으로 실행하면 성공한 -name
내용이 인쇄됩니다 .-name
find
다른 결과를 올바르게 실행하는 방법은 무엇입니까find
?
다른 내 find
에서 실행될 수 있습니다 . 예를 들어 다음과 같은 디렉터리에서 모든 심볼릭 링크를 찾습니다 .-exec
find
lib
find / -type d -name lib -exec find {} -type l \;
/lib/
/var/lib/
등 의 결과를 얻을 수 있습니다./usr/lib/
몇 가지 질문이 있습니다:
- 이는
find
외부의 결과를 기반으로 내부를 실행합니다find
. 한 결과의 모든 결과를 한 번에 사용하려면find
, 즉 다음을 사용하십시오.하나의다른find
. - 내부
find
도 실행해야 하는 경우 , ( 로 입력 ) 또는 를-exec
전달하는 직접적인 방법이 없습니다 . 이는 외부에서 해석되기 때문입니다 . 한 가지 해결책은 다음을 사용하는 것입니다 .{}
;
\;
+
find
xargs
훌륭해), 일반적으로 줄바꿈이 포함된 이름에 실패하지 않도록 POSIX가 아닌 옵션이 필요합니다. 또 다른 해결책은find
두 개의 s 사이에 쉘을 생성하는 것입니다(예:이 다른 답변내 기사를 작성하는 동안 이 문제가 발생했으며 해당 해결 방법을 반복하지 않겠습니다.)
"별도의 인수뿐만 아니라 명령 인수의 어느 곳에나 나타납니다"가 무엇을 의미하는지 이해하지 못합니다.
POSIXfind
연장 필요홀로 {}
. {}.txt
"이 두 문자가 대체되는지 또는 문자열이 변경되지 않고 사용되는지 여부는 foo{}bar
구현에 따라 정의됩니다" 와 같은 매개변수의 경우 . find
귀하의 버전은 또는 같은 인수 find
로 대체되며 {}
매뉴얼에는 이에 대해 명확하게 명시되어 있습니다.{}.txt
foo{}bar
답변2
그냥 해:
find path1 -size 0 -exec sh -c '
for file do
find path2 -name "${file##%/}" -exec ls -ld \{\} +
done' sh {} +
(빈 파일 이름에 와일드카드나 백슬래시가 포함되어 있지 않다고 가정하면 -name
해당 인수는 다음과 같이 처리됩니다.와일드카드 패턴).
GNU에서 왔기 때문에 다음 으로 find
대체할 수도 있습니다 ( 표준 은 아니지만 GNU에 특정 하지만 출력 형식은 구현에 따라 약간씩 다르지만 이식성이 더 좋음).-exec ls -ld \{\} +
-ls
-printf
-ls
-printf
-ls
더 일반적 으로는 GNU 스타일을 사용하고 NUL로 구분된 레코드(예: using 또는 레코드)를 출력하지 않는 한 find
출력을 레코드로 파이프 하고 싶지 않습니다. 대부분의 경우 파이프로 연결하는 것보다 사용하는 것이 더 좋습니다. 더 일반적으로,xargs
xargs -r0
find
-print0
-printf '%f\0'
-exec ... {} +
xargs
카밀의 대답귀하의 접근 방식의 문제점은 잘 설명되어 있으므로 여기서는 반복하지 않겠습니다.
zsh
여기서 대신 쉘을 사용할 수 있습니다 .
for file (path1/**/*(NDL0)) ls -ld path2/**/$file:t(DN)
(와일드카드 문제는 없습니다)
답변3
-I
@muru의 팁에 따라 에서 사용되는 xargs
작업 명령( find
및 의 GNU 구현을 가정 xargs
)은 다음과 같습니다.
find "path1" -size 0 -printf "%f\0" |
xargs -r0 -I mystr find "path2" -name mystr -exec ls -ld {} +
-name
( 인수는 다음과 같이 해석되므로 빈 파일의 이름에는 와일드카드가 포함되지 않은 것으로 가정합니다.와일드카드 패턴)