Existe outra maneira simples de acrescentar linha ao final do arquivo que não seja `>>`?


21

Recentemente, estou ecoando frases curtas em um tree_holearquivo.

Eu estava usando echo 'something' >> tree_holepara fazer este trabalho.

Mas eu sempre estava preocupada com o que se eu introduzisse incorretamente em >vez de >>, já que fazia isso com frequência.

Então, eu criei minha própria função global de bash no bashrc:

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

Mas eu estou querendo saber se existe outra maneira simples de acrescentar linhas ao final de um arquivo. Porque talvez eu precise usá-lo frequentemente em outras ocasiões.

Existe algum?


9
Você não esquecerá que está usando a solução alternativa sempre que digitar>? Uma vez tive um pseudônimo rm="rm -i"e em outro ambiente escrevi rm *aguardando as perguntas de confirmação. Você está aprendendo hábitos perigosos!
Walter A

9
@WalterDepois, sua "solução alternativa" não permite que ele digite> em vez de >>, ele apenas executa "th some_sentence", o que não faz nada se o alias não estiver definido.
usar o seguinte comando

1
@ Ranom832 correto para a sua solução alternativa. O aviso é para uma "solução" como o noclobber. Quando ele usa algo como noclobber em sua casca normal, ele pode usar> quando ele é raiz temporária e quer acrescentar algo.
Walter A

7
@ Random832 & WalterA Normalmente, não digo nada sobre isso quando o vejo, mas achei que um aviso amigável de vez em quando poderia ser útil. O perfil de usuário do Zen não possui muitos detalhes, por isso não tenho certeza se você realmente sabe que a "solução alternativa" é a forma correta. Talvez você deva dizer a "solução alternativa" ou a "solução alternativa" do OP . Talvez você conheça Zen pessoalmente e, portanto, saiba que o dele está correto; nesse caso, perdoe o barulho. Não é grande coisa, eu apenas mencionei isso porque sei que não teria apreciado muito se você tivesse usado esse formulário para falar sobre mim.
Celada

1
@ Zen, você escreveu que está preocupado em digitar incorretamente> em vez de >>. O plano da Celada elimina os riscos em seu ambiente e é uma boa solução para você. Quando você está ajudando seu vizinho (que não possui noclobber ou está usando o ksh) e você perdeu a atenção de um ou dois caracteres, você pode substituir acidentalmente um dos arquivos dele. Então, toda vez que você receber o aviso de noclobber em seu próprio ambiente, graças a Deus ou Celada, diga a si mesmo: Ohh, tenha cuidado, por favor !, sacuda a cabeça e aguarde dois segundos.
Walter A

Respostas:


47

Defina a noclobberopção do shell :

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
Esta é a resposta definitiva. Observe que você ainda pode sobrescrever o arquivo se forçá-lo >|. zshhabilita esse comportamento por padrão.
orion

1
@orion Como você o ativa / desativa no zsh? Não me lembro de desabilitá-lo explicitamente, mas a substituição funciona bem no meu zsh.
muru

2
É setopt noclobbere setopt clobber. Parece que não é exatamente "padrão", depende dos arquivos de configuração que acompanham sua distribuição.
orion

@muru deve funcionar com set [+-]Cqualquer shell moderna
mikeserv

3
@ Zen set +o noclobberna festança, ou set +C.
Ruslan

7

Se você está preocupado que seu arquivo será danificado pelo >operador, você pode alterar o atributo do arquivo para acrescentar apenas:
No sistema de arquivos ext2 / ext3 / ext4 : chattr +a file.txt
No sistema de arquivos XFS :echo chattr +a | xfs_io file.txt

E se você deseja uma função, eu já a criei (usei-a no arquivo de serviço para registrar as saídas), você pode alterá-la para seu propósito:

# 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
Existem alguns problemas com este script. 1) Em geral, você deve colocar aspas duplas em torno das expansões de parâmetros (itens que começam com a $) para evitar problemas de globbing, divisão de palavras e de espaço em branco relacionados. O aplicativo online ShellCheck pode detectar esse e vários outros problemas nos scripts do bash. Em uma nota relacionada "$@"é muito mais seguro que $*.
usar o seguinte comando

3
2) Normalmente, você deve chamar o readcomando com a -ropção para impedir que as barras invertidas na entrada escapem do caractere a seguir. 3) É comum nos scripts bash usar letras minúsculas para nomes de variáveis ​​de script, pois ALL UPPER CASE é usado para variáveis ​​do sistema. Portanto, se você usar maiúsculas para suas próprias variáveis, confundirá as pessoas que leem seu código e poderá acidentalmente derrotar uma variável de sistema que deseja usar posteriormente no script. E se você originar o script, ele estragará as variáveis ​​para comandos subseqüentes.
usar o seguinte comando

3
4) echoé útil para imprimir strings fixas, mas pode fazer coisas inesperadas com dados arbitrários, especialmente em sistemas GNU. É muito mais seguro de usar printf. Veja unix.stackexchange.com/questions/65803/… para mais informações, especialmente a resposta de Stéphane Chazelas.
usar o seguinte comando

3
@PM 2Ring, Hoje eu aprendi muitas coisas com você, muito obrigado .. Vou corrigi-las o mais rápido possível.
Sepahrad Salour

1
Bom trabalho, Sepahrad!
PM 2Ring

3

Use teecom a opção de acréscimo:

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

5
Boa ideia, +1, mas imagino que se o OP estiver preocupado em esquecer um >personagem, ele pode estar preocupado em esquecer a -aopção!
Celada

@ Celada Suponho que sim (mas acho que um erro de digitação por falta de um pressionamento de tecla em um conjunto de pressionamentos repetidos é mais provável do que esquecer uma opção).
muru 12/01

0

muitos programas que podem abrir arquivos para substituição podem abri-los como anexos, por exemplo, gnu dd.

dd conv=notrunc oflag=append of=file

ele pode ler stdin ou um arquivo nomeado no if= parâmetro add 2>/dev/nullpara suprimir a contagem de bytes.


3
É uma boa idéia ™ para testar o código antes de publicá-la como resposta ...
PM 2Ring

1
Recomendar ddé uma má ideia. ddnão grava sua entrada de maneira confiável em sua saída , não quando um deles não é um dispositivo comum de arquivo ou bloco
Gilles 'SO- stop be evil'

@gilles, você está deturpando as informações nesse link. Quando a contagem não é especificada, o dd copiará todos os dados disponíveis, assim como o gato.
Jasen

-1

Eu gostaria de usar um sed(mesmo com cópia de segurança - veja a extensão depois -i):

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

Por que não estou surpreso ... você é um maníaco sedento, Costas. :) (Isso é um elogio, BTW)
PM 2Ring

@ PM2Ring Sim, sou muito perigoso! : P
Costas

Obviamente, a maneira que funciona é fazer uma cópia do arquivo, adicionar o novo texto ao final, excluir o arquivo original e renomear a cópia para o nome original. Isso (1) não funciona se você não tiver acesso de gravação ao diretório, (2) interrompe os links e (3) custa caro se o arquivo for grande. Engraçado que você trouxe a palavra "perigoso"!
G-Man diz 'Restabelecer Monica

-1

Você sempre pode procurar no arquivo de outras maneiras ...

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

... essa sequência de aparência estranha imprime:

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

Mas isso é meio bobo.

Um exemplo mais útil pode se parecer com:

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

Você pode chamar assim:

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

E você terminaria com uma contagem de filelinhas escritas stderrantes da ação de acréscimo.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.