여러 파일에서 탭을 공백으로 변환


11

탭 전체가 흩어져있는 파일이 많이 있으며 모두 공백으로 변환하고 싶습니다. expand명령 에 대해 알고 있지만 불행히도 모든 파일을 사용하여 입력해야합니다. Linux에서 더 쉬운 방법이 있습니까?

답변:


12

다음을 시도하십시오 :

find ./ -type f -exec sed -i 's/\t/ /g' {} \;

네 개의 공백을 원하면 다음을 시도하십시오.

find ./ -type f -exec sed -i 's/\t/    /g' {} \;

각 탭을 단일 공백으로 바꿉니다. 을 사용하여 언급 expand했으므로 텍스트의 정렬을 유지하려고합니다.
garyjohn

's/\t/ /g'한 줄에 두 개 이상의 탭을 교체 해야합니다 .
Daniel Andersson

1
파일이 많은 경우 버전이 지원하는 경우 " find ./ -type f -exec sed -i ’s/\t/ /g’ {} +"(즉, " +"대신 " \;")를 수행하는 상당한 속도 향상 find(그리고 개인적으로 지원하지 않는 버전을 만나지 않았지만 POSIX 표준은 아님) 일부 시스템에서는 발생할 수 있습니다. -exec command {} +설명서의 " "를 참조하십시오 . sed모든 파일 에 대해 하나의 인스턴스를 시작하는 대신 시스템이 지원하는만큼의 파일 이름 인수 (시스템에서 getconf ARG_MAX= 2097152) 로 인수 목록을 작성 xargs하므로 훨씬 적은 sed프로세스 를 시작 합니다.
Daniel Andersson

6
OS X의 버전은 탭 이스케이프 시퀀스를 sed이해하지 못합니다 \t. 리터럴 탭 문자로 바꿀 수 있습니다.이 문자는로 입력 할 수 있습니다 [Ctrl]+V, [Tab].
Jeremy Banks는 STAY HOME이

expand아마도 더 나은보다 sed에서 설명한 바와 같이,이에 대한 : stackoverflow.com/a/11094620/131824
데이비드 Weinraub

6

이를 수행하는 많은 방법이 있습니다. 주의를 기울이지 않거나 Linux에 익숙하지 않은 경우이 작업을 수행하는 동안 발을 쏠 수있는 방법이 많이 있습니다. find편집기와 같은 것을 사용 하거나 수동으로 변환하여 변환하려는 파일 목록을 작성할 수 있다고 가정하면 해당 목록을 다음으로 파이프하십시오.

while read file
do
   expand "$file" > /tmp/expandtmp
   mv /tmp/expandtmp "$file"
done

당신이 발로 자신을 쏠 수있는 한 가지 방법은 오타를 만들어 빈 파일을 지정한 모든 파일 이름으로 가져 와서 모든 파일의 내용을 삭제하는 것입니다. 따라서 백업 한 작은 파일 세트에서 먼저 수행하는 작업을주의하여 테스트하십시오.


3
다음 mv의 성공 여부를 조건부로 지정하십시오 expand.expand ... && mv ...
추후 공지가있을 때까지 일시 중지되었습니다.

expand -t 4탭을 4 칸으로 확장하는 것을 잊지 마십시오 . 또한이 방법은 후행 줄 바꿈을 만들 수 있습니다. 그러나 그렇지 않으면 작동합니다.
mgold

3
find . -type f -iname "*.js" -print0 | xargs -0 -I foo tab2space foo foo

-I foo 각 입력 행에 대해 템플릿 변수 foo를 작성하므로 입력을 두 번 이상 참조 할 수 있습니다.

-print0그리고 -0공간과 경로에 대해이 명령이 작동하므로, 대신 SPACE의 라인 구분자로 \ 0을 사용하는 두 명령을 말한다.


1
find -name \*.js -exec bash -c 'expand -t 4 "$0" | tee "$0"' {} \;

단점 :
파이프 버퍼 크기 ( 64KB ) 보다 큰 파일 은 잘립니다.

장점 : 파이프 버퍼 크기보다 큰
임시 파일
이 잘리지 않습니다.


0

이게 낫다:

find . -name *.java ! -type d -exec bash -c 'expand -t 4 "$0" > /tmp/e && mv /tmp/e "$0"' {} \;

3
왜 이것이 더 낫습니까? /tmp/e다른 파일을 사용하는 경우 파일이 엉망이되기 때문에 사용하는 것이 좋지 않습니다 . 두 명의 사용자가 동시에 이것을 사용하려는 것처럼.
Kevin Panko

0

다음 요구 사항을 염두에두고이 문제를 해결했습니다.

  • 예를 들어 .cpp 또는 .json 파일 만 처리하려면 이름을 기준으로 파일을 필터링하십시오.
  • 병렬 처리를 지원합니다. 파일이 많은 경우 속도가 크게 향상 될 수 있습니다.
  • 솔루션은 사용하기 쉬운 한 줄에 맞아야합니다

"확장"을 사용하면 파일을 적절하게 수정할 수 없으므로 마지막 요구 사항을 충족하기가 가장 어려웠습니다.

나는 다음 해결책을 생각해 냈다.

find . -type f -regextype egrep -regex '.*\.(c|cpp|h|hpp)'  -print0 | xargs -0 -n 1 -P 10 -IFILE bash -c ' ( echo "Processing FILE..." && expand -t 4 "FILE" > /tmp/expand.$$ && mv /tmp/expand.$$ "FILE" ) || exit 255'

다음은 몇 가지 설명입니다.

  • "find"는 처리 할 파일을 찾습니다. "-regextype egrep"은 이름과 "egrep"형식의 정규식을 기준으로 필터링 할 수 있습니다.
  • "-type f"매개 변수는 디렉토리 나 다른 특별한 파일이 아닌 일반 파일과 만 일치하도록합니다.
  • "-regexp"매개 변수는 정규 표현식 자체이며,이 경우 .c, .cpp, .h 또는 .hpp로 끝나는 모든 파일과 일치합니다 (전체 이름이 일치해야하므로 "file.c2"는 우리가 원하는 것입니다)
  • "-print0"은 "find"에게 각 경로의 끝에 문자 0으로 표준 출력의 파일 경로를 인쇄하도록 지시합니다. "xargs"에 대해 "-0"옵션과 함께, 리턴 캐리지가 포함 된 이름을 하나의 도구에서 다른 도구로 전달할 수 있습니다 (아주 드문 경우 일지라도).
  • xargs는 각 경로에 대해 새 프로세스를 시작하지만 ( "-n 1") 최대 10 개의 프로세스를 병렬로 실행할 수 있습니다 ( "-P 10").
  • xargs는 별명 "FILE"을 사용하여 각 파일 경로를 bash 스크립트 인 명령에 전달합니다.
  • bash 스크립트는 "expand"를 호출하고 이름에 현재 프로세스 ID ($$)가 포함 된 임시 파일에 결과를 저장하므로 지정된 파일에서 병렬로 실행되는 모든 프로세스가 다른 임시 파일을 사용합니다
  • 전체 명령은 패턴 (command1 && command2 && command3)을 사용하므로 하위 명령이 오류를 리턴하면 프로세스가 중지됩니다.
  • 이전 "&&"체인에서 오류가 발생하면 bash 스크립트는 종료 코드 255를 리턴하여 xargs가 즉시 중지되게합니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.