이름에 공백이 포함된 생성된 파일 목록을 편집하는 방법

이름에 공백이 포함된 생성된 파일 목록을 편집하는 방법

을 기반으로 하는 파일에서 파생된 비교적 작은 파일 이름 목록이 있습니다 find. 파일 이름에는 공백과 구두점이 포함될 수 있지만 인쇄할 수 없는 문자나 개행 문자는 확실히 포함되어 있지 않습니다.

예를 들어,

Netherlands/Purge (GDPR) 2020-01-09.txt
Netherlands/Purge (GDPR) 2020-01-27.txt
Switzerland/New mailing 2020-01-27.txt

부분적으로 파일 사이를 쉽게 앞뒤로 이동할 수 있도록 이 파일을 그룹( vi file1 file2 file3대신 ) 으로 편집하고 싶습니다 .vi file1; vi file2; vi file3

나는 이미 시작했다생성된 파일 이름 목록을 인수 목록으로 사용 - 공백 포함 , 표준 find -print0 | xargs -0 mycommand솔루션이 있습니다. 불행하게도 mycommand편집자가 편집자인 경우에는 작동하지 않습니다. 왜냐하면 xargs편집할 파일 세트를 모으는 것이 가능하지만,표준 입력이미 파이프라인에서 가져온 것이므로 편집기를 제자리에서 실행할 수 있는 방법이 없습니다. 파이프 자체 find -exec vi {} +뿐만 아니라 파일 이름 집합의 유효성을 검사하기 위해 파이프를 사용하고 있기 때문에 그럴 수 없습니다 find.

다른 옵션은 복사하여 붙여넣고 파일 이름 목록을 결합하고 따옴표로 묶은 다음 결과를 앞에 추가하는 것입니다 vi. 이 세 파일의 경우 이는 간단하지만 일반적으로 쉽게 재사용할 수 있는 솔루션은 아닙니다.

vi 'Netherlands/Purge (GDPR) 2020-01-09.txt' 'Netherlands/Purge (GDPR) 2020-01-27.txt' 'Switzerland/New mailing 2020-01-27.txt'

내가 선호하는 쉘로 GNU/Linux 플랫폼이 있는 경우 bash(중요하다면) 생성된 파일 목록과 같은 것을 어떻게 편집할 수 있습니까?

답변1

Bash에 있기 때문에

#!/bin/bash
readarray -d '' -t files < <(find path -type f -print0)
vi -- "${files[@]}"

find path -type f -print0실제 파이프로 교체하십시오 .

파일에 개행 문자가 없더라도 사용자는 이러한 파일 이름에 대한 지원을 추가했습니다.글렌 잭맨.

buffer 대신 탭을 사용하려면 다음 플래그를 vi추가하세요 .-pvi -p ...


배관이 필요하지 않은 경우 이 옵션을 직접 사용할 수 있습니다 -exec.

find path -type f -exec vi -- {} +

답변2

불행하게도 mycommand가 편집기인 경우에는 작동하지 않습니다. 왜냐하면 xargs가 편집할 파일 세트를 조합할 수 있지만 stdin은 이미 파이프에서 가져오고 편집기를 제자리에서 실행할 수 있는 방법을 볼 수 없기 때문입니다.

이 접근 방식은 GNU Findutils 매뉴얼 페이지에 문서화되어 있습니다 xargs.

   -o, --open-tty
          Reopen stdin as /dev/tty in the child process  before  executing
          the  command.  This is useful if you want xargs to run an inter‐
          active application.

이 방법으로 사용할 수 있습니다

find . -name 'pattern' -print0 | xargs -0o vim

그러나 이것은 새로운 기능입니다. xargs 4.4.2가 있는 이전 시스템에서는 볼 수 없습니다. xargs 4.7.0이 있는 Ubuntu 18에서는 볼 수 있습니다.

지금은 10년 전과 같은 옵션이 xargs없을 수도 있지만 -oBash 프로세스 대체는 10년 전에 존재했으며 표준 입력 대신 파일에서 읽는 옵션이 xargs있었습니다 .-a

따라서 이 문제는 해결될 수 있습니다. 다음과 같이 될 필요는 없습니다 xargs -o.

xargs -0 -a <(find . -name 'pattern' -print0) vim

xargs인수로 받은 파일을 읽고 있기 때문에 (생각하는 대로) 표준 입력을 유지합니다.

답변3

내가 얻은 의견에서 다음은 귀하의 명령입니다.

find -type f -mtime +14 -mtime -22 -iname '*.xml' | while IFS= read -f x; do xmlstarlet sel -T -t -v '//magicElement' -n "$x" | grep -q magicValue && echo "$x"; done 

while-exec sh -c '...'-loop로 파이프하는 대신 파이프를 사용하여 파일을 필터링할 수 있습니다 .

find -type f -mtime +14 -mtime -22 -iname '*.xml' \
  -exec sh -c 'xmlstarlet sel -T -t -v "//magicElement" "$1" | grep -q magicValue' find-sh {} \; \
  -exec vi -- {} +

노력하다:

세 가지 파일을 고려하십시오.

.
├── a:<magicElement>magicValue</magicElement>
├── b:<magicElement>magicValue</magicElement>
└── c:<magicElement>someOtherValue</magicElement>

$ find . -type f \
  -exec sh -c 'xmlstarlet sel -T -t -v "//magicElement" "$1" | grep -q magicValue' find-sh {} \; \
  -exec echo vi -- {} +

산출:

vi -- ./a ./b

답변4

제가 수년에 걸쳐 이 문제를 해결하기 위해 사용해 온 두 가지 추악한 방법은 다음과 같습니다. 둘 다 X가 필요합니다.

find ... -print0| ...| xargs -0r gvim -f

find ... -print0| ...| xargs -0r xterm -e vim

SSH를 통해서도 작동합니다.

관련 정보