1.grep | xargs mv

1.grep | xargs mv

한 디렉토리에 그런 파일이 몇 개 있습니다

00.01.02 0000 some filename 1.pdf
00.01.02 0000 some filename 1.txt
02.03.07 0163 another filename 2.pdf
02.03.07 0163 another filename 2.txt

특정 문자열이 포함된 모든 txt 파일을 찾은 다음 이 txt 파일과 해당 pdf 파일을 다른 디렉터리로 이동해야 합니다.

이 작업을 수행하는 가장 좋은 방법은 무엇입니까?

답변1

3가지 옵션이 있습니다. 기본 아이디어는 다음과 같습니다.

  1. grep | xargs mv
  2. grep | parallel mv
  3. find -exec grep -q -exec mv

1.grep | xargs mv

사용 grepxargs:

grep -FlZ "some string" *.txt \
| xargs -0 -I{} sh -c 'echo mv "$1" "${1%.*}.pdf" some/other/directory' xargs-sh {}

grep:

  • -F패턴이 아닌 전체 문자열과 일치
  • -l일치하는 파일 이름만 출력
  • -Z파일 이름 사이에 0 구분 기호를 출력합니다. (파일 이름에 개행 문자가 허용되어 개행 문자를 구분 기호로 사용할 수 없기 때문에 이는 중요합니다.)

xargs:

  • -00으로 구분된 데이터를 읽습니다.

2.grep | parallel mv

해당 PDF 파일 이름을 얻으려면 를 xargs사용하여 서브셸을 호출해야 합니다 .sh -c

그 대신에 멋진 기능을 활용할 수도 있습니다 GNU parallel!!

grep -FlZ "some string" *.txt \
| parallel -0 -j1 echo mv {} {.}.pdf some/other/directory
  • -j1한 번에 하나의 직업만
  • {}파일 이름
  • {.}확장자가 없는 파일 이름

삼.find -exec grep -q -exec mv

그리고 또 다른 대안은 다음을 사용하는 것 find입니다.

find . -maxdepth 1 -name "*.txt" \
-exec grep -Fq "some string" {} \; \
-exec sh -c 'echo mv "$1" "${1%.*}.pdf" some/other/location' find-sh {} \;
  • -maxdepth 1재발하지 않도록
  • grep -q파일 이름 대신 오류 코드만 얻으려면 두 번째는 -exec첫 번째가 성공한 경우에만 실행됩니다.
  • 두 번째는 기본적으로 첫 번째 옵션 -exec과 동일합니다 .xargs
  • 파일 이름을 전달하지 않고 처리하므로 0으로 구분된 출력 작업을 수행할 필요가 없습니다 find.

각 옵션에 대해 echo출력이 만족스러우면 제거하세요.

답변2

문제를 여러 조각으로 나누세요.

"현재 디렉터리에서 주어진 문자열을 포함하는 모든 텍스트 파일을 찾아야 합니다."

grep -F "text string just as written (no regex)" *.txt

"나는 ~을 원한다파일 이름그 파일들 중"

grep -l -F "text string" *.txt

"각 파일에 대해..."

for...each는 while/do/done파일 목록을 전달할 구성을 사용하여 수행합니다. 실행할 수 있는 각 파일에 대해무엇, 변수에 액세스할 수 있습니다 $file.

grep -l -F "text string" *.txt \
| while IFS= read -r file ; do
...something...
done

"뭔가"는

"...txt 파일과 해당 pdf 파일을 이동합니다..."

따라서 ".txt"가 없는 기본 이름이 필요합니다.

BASE=$( basename ${file} .txt )

그리고 마지막으로 모든 것을 종합하면 다음과 같습니다.

grep -l -F "text string" *.txt \
| while IFS= read -r file ; do \
    BASE=$( basename ${file} .txt )
    mv ${BASE}.txt /some/other/dir
    mv ${BASE}.pdf /some/other/dir
done

(참고로 이는 각파일그렇지 않으면 경로가 제거되므로 경로가 없습니다 basename.)

답변3

command 가 없으면 아래와 같이 parallel두 가지로 수행하십시오.xargs

grep -l 'search string' *.txt | xargs -I {} basename {} .txt | xargs -I {} cp {}.pdf /destination-directory

관련 정보