이것은 아마도 복잡한 해결책 일 것입니다 .
">>"와 같은 간단한 연산자를 찾고 있지만 앞에 추가합니다.
그것이 존재하지 않을까 걱정됩니다. 나는 다음과 같은 일을해야 할 것이다.
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 header
my.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-msg
in-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
. 빈 줄 두 개가 생깁니다.-s
ed의 진단 정보 출력을 억제합니다.
이 겪고과 관련하여, 나는 발견 VIM-좋아하는 분들을 위해도가 좋은 것을 :
[core]
editor = vim -c ':normal gg'
이럴 일관되고 안정적으로 어떤 두 파일의 크기 일 것이라고이 더 쉘 솔루션입니다 (결코 하나가 될 수 없습니다) myheader
및 myfile
. 그 이유는 임시 파일을 되풀이하지 않고 (예를 들어 exec 3<>myfile
, 파이핑 대상 등과 같은 구문을 통해) 셸이 임시 파일로 자동 반복되지 않도록 하기 위해서입니다 tee
.
찾고있는 "실제"솔루션은 파일 시스템과 함께 작동해야하므로 사용자 영역에서 사용할 수 없으며 플랫폼에 따라 다릅니다. 사용중인 파일 시스템 포인터를 파일 시스템 포인터 myfile
의 현재 값으로 수정하도록 요청하고 있습니다. 대한 myheader
과하면 파일 시스템에서 대체 EOF
의 myheader
가 가리키는 현재의 파일 시스템 주소로 체인으로 연결된 링크 myfile
. 이것은 사소하지 않으며 분명히 비 수퍼 유저가 수행 할 수 없으며 아마도 수퍼 유저도 수행 할 수 없습니다. inode와 함께 플레이하십시오.
그러나 루프 장치를 사용하여 다소 위조 할 수 있습니다. 예를 들어이 SO 스레드를 참조하십시오 .
mktemp
? 나중에 임시 파일을 정리할 수 있습니다.