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.
  • find파일 이름을 전달하지 않고 대신 처리되므로 0으로 구분된 출력을 수행할 필요가 없습니다 .

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

parallel명령이 없으면 xargs다음 두 가지를 수행하십시오.

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

관련 정보