Czy istnieje inny prosty sposób dołączenia wiersza na końcu pliku niż `>>`?


21

Ostatnio powtarzam krótkie zdania do tree_holepliku.

Korzystałem echo 'something' >> tree_holez tej pracy.

Ale zawsze martwiłem się tym, co jeśli wprowadzę w błąd >zamiast >>, ponieważ robiłem to często.

Więc stworzyłem własny bashrc w bashrc:

function th { echo "$1" >> /Users/zen1/zen/pythonstudy/tree_hole; }
export -f th

Ale zastanawiam się, czy istnieje inny prosty sposób dodawania wierszy na końcu pliku. Ponieważ być może będę musiał używać tego często przy innych okazjach.

Czy jest jakiś?


9
Czy nie zapomnisz, że używasz obejścia przy każdym wejściu>? Kiedyś miałem alias rm="rm -i"i w innym środowisku pisałem rm *czekając na pytania potwierdzające. Uczysz się niebezpiecznych nawyków!
Walter A

9
@WalterAer, jego „obejście” nie pozwala mu pisać> zamiast >>, po prostu uruchamia „th some_sentence”, co nie robi nic, jeśli alias jest niezdefiniowany.
Random832

1
@ Ranom832 poprawi swoje obejście. Ostrzeżenie dotyczy „rozwiązania” takiego jak noclobber. Kiedy używa czegoś takiego jak noclobber w swojej normalnej powłoce, może użyć>, gdy jest tymczasowym rootem i chce coś dodać.
Walter A,

7
@ Random832 i WalterA Zwykle nic nie mówię o tym, kiedy to widzę, ale doszedłem do wniosku, że od czasu do czasu może być przydatne przyjazne powiadomienie. Profil użytkownika Zen nie zawiera zbyt wielu szczegółów, więc nie jestem pewien, czy naprawdę wiesz, że jego „obejście” jest poprawne. Może powinieneś powiedzieć o ich „obejściu” lub „obejściu” PO . Być może znasz Zen osobiście i dlatego wiesz, że jego poprawność jest prawidłowa, w takim przypadku proszę wybacz hałas. Nie jest to wielka sprawa, po prostu wspominam o tym, ponieważ wiem, że nie doceniłbym tego zbytnio, gdybyś użył tego formularza do mówienia o mnie.
Celada,

1
@Zen, Napisałeś, że martwisz się błędnym wprowadzeniem> zamiast >>. Plan Celady usunie ryzyko w twoim otoczeniu i jest dla ciebie dobrym rozwiązaniem. Kiedy pomagasz swojemu sąsiadowi (który nie ma noclobbera lub używa ksh) i straciłeś uwagę na jedną lub dwie> znaki, możesz przypadkowo zastąpić jeden z jego plików. Więc za każdym razem, gdy pojawi się ostrzeżenie o noclobber w swoim otoczeniu, dzięki Bogu lub Celadzie, powiedz sobie: Och, bądź ostrożny, proszę !, potrząśnij głową i poczekaj dwie sekundy.
Walter A

Odpowiedzi:


47

Ustaw noclobberopcję powłoki :

bash-3.2$ set -o noclobber
bash-3.2$ echo hello >foo
bash-3.2$ echo hello >foo
bash: foo: cannot overwrite existing file
bash-3.2$ 

3
To jest ostateczna odpowiedź. Pamiętaj, że nadal możesz zastąpić plik, jeśli wymusisz go >|. zshdomyślnie włącza to zachowanie.
orion

1
@orion Jak en / wyłączyć to w Zsh? Nie pamiętam, aby to wyraźnie wyłączało, ale nadpisywanie działa dobrze na moim Zsh.
muru

2
To jest setopt noclobberi setopt clobber. Wygląda na to, że nie jest dokładnie „domyślny”, zależy to od plików konfiguracyjnych dostarczonych z dystrybucją.
orion

@muru powinien współpracować z set [+-]Ckażdą nowoczesną powłoką
mikeserv

3
@Zen set +o noclobberw bash, lub set +C.
Ruslan

7

Jeśli obawiasz się, że plik zostanie uszkodzony przez >operatora, możesz zmienić atrybut pliku tak, aby dołączał tylko:
W systemie plików ext2 / ext3 / ext4 : chattr +a file.txt
W systemie plików XFS :echo chattr +a | xfs_io file.txt

A jeśli chcesz funkcji, już stworzyłem funkcję dla siebie (użyłem jej w pliku usługi do rejestrowania wyników), możesz ją zmienić do własnych celów:

# This function redirect logs to file or terminal or both!
#@ USAGE: log option data
# To the file     -f file
# To the terminal -t
function log(){
        read -r data       # Read data from pipe line

        [[ -z ${indata} ]] && return 1    # Return 1 if data is null

        # Log to /var/log/messages
        logger -i -t SOFTWARE ${data}

        # While loop for traveling on the arguments
        while [[ ! -z "$*" ]]; do
                case "$1" in
                        -t)
                                # Writting data to the terminal
                                printf "%s\n" "${data}"
                                ;;
                        -f) 
                                # Writting (appending) data to given log file address
                                fileadd=$2
                                printf "%s %s\n" "[$(date +"%D %T")] ${data}" >> ${fileadd}
                                ;;
                        *)
                                ;;
                esac
                shift           # Shifting arguments
        done
}

2
Istnieje kilka problemów z tym skryptem. 1) Powinieneś zwykle umieszczać podwójne cudzysłowy wokół rozszerzeń parametrów (rzeczy, które zaczynają się od a $), aby uniknąć globowania, podziału słów i powiązanych problemów z białymi znakami. Internetowa aplikacja ShellCheck może wykryć ten i wiele innych problemów w skryptach bash. Podobna uwaga "$@"jest znacznie bezpieczniejsza niż $*.
PM 2,

3
2) Zwykle powinieneś wywołać readpolecenie z -ropcją, aby zapobiec odwrotnym ukośnikom na wejściu przed ucieczką następującego znaku. 3) W skryptach bash zwykle używa się małych liter w nazwach zmiennych skryptu, ponieważ dla zmiennych systemowych używana jest WSZYSTKIE GÓRNA LICZBA. Jeśli więc użyjesz wielkich liter do własnych zmiennych, pomylisz ludzi, którzy czytają Twój kod, i możesz przypadkowo zablokować zmienną systemową, której chcesz użyć później w skrypcie. A jeśli źródła skryptu, to sprać zmienne dla kolejnych poleceń.
PM 2,

3
4) echojest przydatny do drukowania stałych ciągów, ale może robić nieoczekiwane rzeczy z dowolnymi danymi, szczególnie w systemach GNU. Jest o wiele bezpieczniejszy w użyciu printf. Aby uzyskać więcej informacji, zobacz unix.stackexchange.com/questions/65803/ ..., zwłaszcza odpowiedź Stéphane'a Chazelasa.
PM 2,

3
@PM 2Ring, Dzisiaj nauczyłem się od ciebie wielu rzeczy, wielkie dzięki .. Naprawię je jak najszybciej.
Sepahrad Salour,

1
Dobra robota, Sepahrad!
PM 2,

3

Użyj teez opcją dołączania:

foo | tee -a some-file
# or
tee -a some-file <<EOF
blah blah
EOF
# or 
tee -a some-file <<<"blah blah"

5
Dobry pomysł, +1, ale wyobrażam sobie, że jeśli OP martwi się o zapomnienie >postaci, mogą martwić się zapomnieniem -aopcji!
Celada,

@Celada Chyba tak (ale przypuszczam, że literówka z pominięciem jednego naciśnięcia klawisza w zestawie powtarzających się naciśnięć klawiszy jest bardziej prawdopodobna niż zapomnienie opcji).
muru

0

wiele programów, które potrafią otwierać pliki do zastąpienia, może alternatywnie otwierać je w celu dołączenia, np. gnu dd.

dd conv=notrunc oflag=append of=file

może odczytać standardowe wejście lub plik o nazwie w if= parametrze add, 2>/dev/nullaby pominąć liczbę bajtów.


3
Dobrym pomysłem ™ jest przetestowanie kodu przed opublikowaniem go jako odpowiedzi ...
PM 2 w dniu

1
Polecanie ddto zły pomysł. ddnie zapisuje niezawodnie swoich danych wejściowych na wyjściu , nawet jeśli jeden z nich nie jest zwykłym plikiem lub urządzeniem blokującym
Gilles „SO- przestań być zły”

@ gilles, podajesz w błąd informacje pod tym linkiem, jeśli nie podano liczby, dd skopiuje wszystkie dostępne dane, tak samo jak cat.
Jasen

-1

Chciałbym użyć sed(nawet z kopią zapasową - patrz rozszerzenie później -i):

sed -i.bak '$ a\something' /Users/zen1/zen/pythonstudy/tree_hole

Dlaczego nie jestem zaskoczony ... jesteś szalonym maniakiem, Costas. :) (To komplement, BTW)
PM 2Ring

@ PM2Ring Tak, jestem bardzo niebezpieczny! : P
Costas

Oczywiście sposób, w jaki działa to zrobić kopię pliku, dodać nowy tekst na końcu, a następnie usunąć oryginalny plik i zmienić nazwę kopii na pierwotną nazwę. To (1) nie działa, jeśli nie masz dostępu do zapisu do katalogu, (2) zrywa linki, a (3) jest kosztowne pod względem zasobów, jeśli plik jest duży. Zabawne, że przywołałeś słowo „niebezpieczne”!
G-Man mówi „Przywróć Monikę”

-1

Zawsze możesz przeszukać plik na inne sposoby ...

seq 10000000 >f
{ wc -l >&2; echo new line\!; } <>f >&0; \
{ wc -l >&2; echo new line\!; } <>f >&0; \
{ wc -l >&2; echo new line\!; } <>f >&0; \
{ wc -l >&2; echo new line\!; } <>f >&0; \
{ wc -l >&2; echo new line\!; } <>f >&0; \
wc -l f; tail f

... dziwnie wyglądające odbitki sekwencji:

10000000
10000001
10000002
10000003
10000004
10000005 f
9999996
9999997
9999998
9999999
10000000
new line!
new line!
new line!
new line!
new line!

Ale to trochę głupie.

Bardziej przydatny przykład może wyglądać następująco:

 apnd() if    shift
        then  wc -l  >&2
              printf "$@"
        fi    <>"$1" >&0

Możesz to nazwać tak:

 apnd /path/to/file          \
      "${printf_fmt_string}" \
       arbitrary list of strings

I skończyłbyś z liczbą filewierszy zapisanych stderrtuż przed operacją dołączania.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.