이것은 아마도 복잡한 해결책 일 것입니다 .
">>"와 같은 간단한 연산자를 찾고 있지만 앞에 추가합니다.
그것이 존재하지 않을까 걱정됩니다. 나는 다음과 같은 일을해야 할 것이다.
mv myfile tmp 고양이 myheader tmp> myfile
더 똑똑한 것이 있습니까?
이것은 아마도 복잡한 해결책 일 것입니다 .
">>"와 같은 간단한 연산자를 찾고 있지만 앞에 추가합니다.
그것이 존재하지 않을까 걱정됩니다. 나는 다음과 같은 일을해야 할 것이다.
mv myfile tmp 고양이 myheader tmp> myfile
더 똑똑한 것이 있습니까?
답변:
아래 의 핵 은 빠른 커프스 답변으로 많은 찬사를 받았습니다. 그런 다음 질문이 더 대중화되고 시간이 지남에 따라 분노한 사람들은 문제가 발생했지만 이상한 일이 발생하거나 전혀 작동하지 않았다고보고하기 시작했습니다. 이러한 재미.
이 솔루션은 시스템에서 파일 디스크립터의 정확한 구현을 활용하며, 구현은 nix마다 크게 다르기 때문에 성공은 전적으로 시스템에 따라 다르고 결정적으로 이식 할 수 없으며, 모호하게 중요한 것에 의존해서는 안됩니다.
이제, 그 모든 대답을 벗어난 대답은 다음과 같습니다.
파일에 대한 다른 파일 디스크립터를 exec 3<> yourfile작성하면 ( ) 파일에 쓰는 ( >&3) 동일한 파일 딜레마에 대한 읽기 / 쓰기를 극복하는 것으로 보입니다. awk가있는 600K 파일에서 작동합니다. 그러나 'cat'을 사용하여 동일한 트릭을 시도하면 실패합니다.
접두사를 awk ( -v TEXT="$text")에 변수로 전달하면 리터럴 따옴표 문제를 극복하여 'sed'로이 트릭을 수행하지 못하게합니다.
#!/bin/bash
text="Hello world
What's up?"
exec 3<> yourfile && awk -v TEXT="$text" 'BEGIN {print TEXT}{print}' yourfile >&3
이것은 여전히 임시 파일을 사용하지만 적어도 한 줄에 있습니다.
echo "text" | cat - yourfile > /tmp/out && mv /tmp/out yourfile
크레딧 : BASH : 파일 앞에 텍스트 / 줄 추가
-후 cat?
echo -n "text"
yourfile심볼릭 링크 인 경우 원하는 작업을 수행하지 않습니다.
echo '0a
your text here
.
w' | ed some_file
ed는 표준 편집기입니다! http://www.gnu.org/fun/jokes/ed.msg.html
0r header.file
echo -e '0a\nyour text here\n.\nw' | ed some_file
John Mee : 메소드가 작동한다고 보장되지 않으며 4096 바이트 이상의 물건을 추가하면 실패 할 것입니다 (적어도 gnu awk에서 발생하는 일이지만 다른 구현에는 비슷한 제약 조건이 있다고 가정합니다). 이 경우에는 실패 할뿐만 아니라 자체 출력을 읽을 수있는 무한 루프로 들어가서 사용 가능한 모든 공간이 채워질 때까지 파일이 커집니다.
직접 해보십시오.
exec 3<>myfile && awk 'BEGIN{for(i=1;i<=1100;i++)print i}{print}' myfile >&3
(경고 : 잠시 후 죽이거나 파일 시스템을 채울 것입니다)
또한 파일을 그런 식으로 편집하는 것은 매우 위험하며 파일을 편집하는 동안 (충돌, 디스크 꽉 참) 어떤 일이 발생하는 경우 파일이 일관성이없는 상태로 유지되는 것이 거의 보장되므로 매우 나쁜 조언입니다.
임시 파일이 없으면 불가능하지만 여기에는 oneliner가 있습니다.
{ echo foo; cat oldfile; } > newfile && mv newfile oldfile
ed 또는 perl과 같은 다른 도구를 사용하여 임시 파일없이 수행 할 수 있습니다.
제어하는 컴퓨터에서이 패키지가 필요한 경우 "moreutils"패키지를 설치하고 "sponge"을 사용하십시오. 그럼 당신은 할 수 있습니다 :
cat header myfile | sponge myfile
{ echo "prepended text"; cat myfile } | sponge myfile
편집하려는 파일이 my.txt라고 가정
$cat my.txt
this is the regular file
앞에 추가하려는 파일은 헤더입니다.
$ cat header
this is the header
헤더 파일에 마지막 빈 줄이 있어야합니다.
이제 앞에 붙일 수 있습니다
$cat header <(cat my.txt) > my.txt
당신은 결국
$ cat my.txt
this is the header
this is the regular file
내가 아는 한 이것은 'bash'에서만 작동합니다.
this is the headermy.txt에 두 줄로 끝났습니다 . Bash를 업데이트 한 후에도 4.3.42(1)-release동일한 결과를 얻습니다.
<(...)) 의 명령이 기록 하는 FIFO (파이프)를 생성하므로이 기술이 작동하지 않으면 전체를 읽을 수 있다는 보장my.txt 이 없습니다.
쉘 스크립트에서 어려워지는 일을 시작하려고 할 때, "적절한"스크립팅 언어 (Python / Perl / Ruby / etc)로 스크립트를 다시 작성하는 것이 좋습니다.
파일에 줄을 추가하는 것과 같이 파이프를 통해이 작업을 수행 할 수는 cat blah.txt | grep something > blah.txt없습니다. sponge설치할 수 있는 작은 유틸리티 명령 이 있습니다 (그러면 cat blah.txt | grep something | sponge blah.txt파일 내용을 버퍼링 한 다음 파일에 씁니다). 임시 파일과 비슷하지만 명시 적으로 할 필요는 없습니다. 그러나 나는 그것이 Perl보다 "나쁜"요구 사항이라고 말할 것이다.
awk 또는 이와 유사한 방법으로 수행 할 수있는 방법이있을 수 있지만 쉘 스크립트를 사용해야하는 경우 임시 파일이 훨씬 쉬운 방법이라고 생각합니다.
편집 : 이것은 고장났습니다. 참조 고양이와 티와 파일에 붙이는 때 이상한 행동을
덮어 쓰기 문제에 대한 해결 방법은 다음을 사용하는 것입니다 tee.
cat header main | tee main > /dev/null
fled에서 이미 제안한 것처럼 단순히 ed 명령을 사용하지 않는 이유는 무엇입니까?
ed는 전체 파일을 메모리로 읽고 자동으로 내부 파일 편집을 수행합니다!
따라서 파일이 그렇게 크지 않으면 ...
# cf. "Editing files with the ed text editor from scripts.",
# http://wiki.bash-hackers.org/doku.php?id=howto:edit-ed
prepend() {
printf '%s\n' H 1i "${1}" . wq | ed -s "${2}"
}
echo 'Hello, world!' > myfile
prepend 'line to prepend' myfile
또 다른 해결 방법은 Jürgen Hötzel이 제안한대로 열린 파일 핸들을 사용하여 sed 's / c / d /'myFile에서 myFile로 출력을 리디렉션하는 것입니다.
echo cat > manipulate.txt
exec 3<manipulate.txt
# Prevent open file from being truncated:
rm manipulate.txt
sed 's/cat/dog/' <&3 > manipulate.txt
물론이 모든 것을 한 줄에 넣을 수 있습니다.
고정 텍스트를 앞에 추가하는 "임시 파일 없음"에 대한 cb0 솔루션의 변형 :
echo "text to prepend" | cat - file_to_be_modified | ( cat > file_to_be_modified )
다시 이것은 하위 쉘 실행 ((..))에 의존하여 cat이 입력 및 출력을 위해 동일한 파일을 갖는 것을 피합니다.
참고 :이 솔루션을 좋아했습니다. 그러나 내 Mac에서는 원본 파일이 손실됩니다 (생각해서는 안됩니다). 다음과 같이 솔루션을 작성하여 해결할 수 있습니다. echo "prepend to text"| 고양이-file_to_be_modified | 고양이> tmp_file; mv tmp_file 파일 _to_be_modified
경고 : OP의 요구를 충족시키기 위해서는 약간의 작업이 더 필요합니다.
그의 혼란에도 불구하고 @shixilun의 sed 접근법을 작동시키는 방법이 있어야합니다. 가. 쉘 명령 (A 나오지도 대체 문자열로 파일을 읽을 때 예를 들어 'N \'와 개행 문자를 대체 공백 탈출 bash는 명령이어야합니다 vis및 cat인쇄 할 수없는 문자를 처리 할 수 있지만 공백이 해결되지 않도록 영업의 문제:
sed -i -e "1s/^/$(cat file_with_header.txt)/" file_to_be_prepended.txt
대체 스크립트의 줄 바꿈 문자로 인해 실패합니다.이 문자는 줄 연속 문자 ()가 앞에 붙어 있고 &가 뒤에 있어야 쉘과 sed를 행복하게 유지할 수 있습니다. 이 SO 답변
sed 전역 검색이 아닌 검색-대체 명령의 경우 크기 제한이 40K (패턴 뒤에 / g 없음)이므로 익명으로 경고 한 awk의 무서운 버퍼 오버런 문제를 피할 수 있습니다.
솔루션 printf:
new_line='the line you want to add'
target_file='/file you/want to/write to'
printf "%s\n$(cat ${target_file})" "${new_line}" > "${target_file}"
당신은 또한 할 수 있습니다 :
printf "${new_line}\n$(cat ${target_file})" > "${target_file}"
그러나이 경우 %대상 파일의 내용을 포함하여 해석 할 수 없으며 결과를 망칠 수있는 곳 이 없어야 합니다.
echo더 안전한 옵션처럼 보입니다. echo "my new line\n$(cat my/file.txt)" > my/file.txt
${new_line}타겟 파일이 아닌의 퍼센트에 대해서만 경고했습니다
@fluffle의 ed 접근법을 좋아합니다. 최고. 결국 도구의 명령 행 스위치와 스크립트 편집기 명령은 본질적으로 동일합니다. 스크립팅 된 편집기 솔루션 "청결성"이 더 적거나 그렇지 않은 것을 보지 못했습니다.
메시지를 커밋하기 위해 .git/hooks/prepare-commit-msgin-repo .gitmessage파일을 추가하기 위해 하나의 라이너가 추가되었습니다 .
echo -e "1r $PWD/.gitmessage\n.\nw" | ed -s "$1"
예 .gitmessage:
# Commit message formatting samples:
# runlevels: boot +consolekit -zfs-fuse
#
원본 템플릿의 파일 위에 비어있는 쓰기 준비가 된 줄을 남겨두기 때문에 1r대신에 하고 0r있습니다. 빈 줄을 그 위에 두지 마십시오 .gitmessage. 빈 줄 두 개가 생깁니다.-sed의 진단 정보 출력을 억제합니다.
이 겪고과 관련하여, 나는 발견 VIM-좋아하는 분들을 위해도가 좋은 것을 :
[core]
editor = vim -c ':normal gg'
이럴 일관되고 안정적으로 어떤 두 파일의 크기 일 것이라고이 더 쉘 솔루션입니다 (결코 하나가 될 수 없습니다) myheader및 myfile. 그 이유는 임시 파일을 되풀이하지 않고 (예를 들어 exec 3<>myfile, 파이핑 대상 등과 같은 구문을 통해) 셸이 임시 파일로 자동 반복되지 않도록 하기 위해서입니다 tee.
찾고있는 "실제"솔루션은 파일 시스템과 함께 작동해야하므로 사용자 영역에서 사용할 수 없으며 플랫폼에 따라 다릅니다. 사용중인 파일 시스템 포인터를 파일 시스템 포인터 myfile의 현재 값으로 수정하도록 요청하고 있습니다. 대한 myheader과하면 파일 시스템에서 대체 EOF의 myheader가 가리키는 현재의 파일 시스템 주소로 체인으로 연결된 링크 myfile. 이것은 사소하지 않으며 분명히 비 수퍼 유저가 수행 할 수 없으며 아마도 수퍼 유저도 수행 할 수 없습니다. inode와 함께 플레이하십시오.
그러나 루프 장치를 사용하여 다소 위조 할 수 있습니다. 예를 들어이 SO 스레드를 참조하십시오 .
mktemp? 나중에 임시 파일을 정리할 수 있습니다.