Por que não existe nenhum comando shell para criar arquivos?

27

Atenção por FAVOR:

Estou não perguntando como fazer um arquivo a partir da linha de comando!


Eu tenho usado touchpara criar arquivos há anos sem prestar atenção que seu principal objetivo é outra coisa. Se alguém quiser criar um arquivo a partir da linha de comando, há muitas possibilidades:

touch foo.bar
> foo.bar
cat > foo.bar
echo -n > foo.bar
printf '' > foo.bar

E tenho certeza que há mais.

Mas o fato é que nenhum dos comandos acima foi projetado para criar arquivos. Por exemplo, man touchsugere que este comando é para alterar os carimbos de data / hora do arquivo. Por que um sistema operacional tão completo quanto o Unix (ou Linux) não possui um comando projetado apenas para criar arquivos?

Pouya
fonte
35
Por que você iria desorganizar o sistema para adicionar um comando para fazer algo que pode ser feito de uma dúzia de maneiras com ferramentas que já existem?
Michael Kohne
4
Por que não há comando para ler arquivos de / para streams / stdin / out? Todo mundo usa o comando destinado à catconexão!
SF.
2
@ MichaelKohne, entendo seu ponto de vista, com todo o respeito, tenho um problema com isso. Com essa abordagem, existem muitos comandos que estão apenas sobrecarregando o sistema. Por que usar morequando lessfaz mais do que aquilo more!? Ou dire ls. Embora eu esteja ciente dos problemas de compatibilidade.
Pouya
9
moreantecede a criação de less. lessfoi criado especificamente para solucionar deficiências de more. moreainda existe por motivos de compatibilidade com versões anteriores. dire lssão, para a maioria das intenções e propósitos, o mesmo executável - eles diferem apenas em alguns bytes. Uma nova ferramenta que se destina especificamente para a criação de arquivos faria menos do que as ferramentas existentes, e como tal seria uma regressão, e não uma melhoria, como no caso da lessvs more.
lanzz
11
Além disso, precisamos examinar o legado, o Unix foi criado quando cada byte foi contado. Por que criar um utilitário para uma tarefa que você pode executar com um utilitário já existente?
Thomas

Respostas:

38

Eu diria porque quase nunca é necessário criar um arquivo vazio que você não preencha com conteúdo imediatamente na linha de comando ou no script de shell.

Não há absolutamente nenhum benefício em criar um arquivo primeiro e depois usar o redirecionamento de E / S para gravar no arquivo, se você puder fazê-lo em uma única etapa.

Nos casos em que você realmente deseja criar um arquivo vazio e deixá-lo, eu argumentaria que > "${file}"não poderia ser mais breve e mais elegante.

TL; DR : ele não existe porque a criação de arquivos vazios geralmente não tem uso e, nos casos em que existe, já existem inúmeras opções disponíveis para atingir esse objetivo.

Por outro lado, usar touchsomente funciona se o arquivo não existir, enquanto as opções usando o redirecionamento sempre truncarão o arquivo, mesmo que ele exista (portanto, tecnicamente, essas soluções não são idênticas). > fooé o método preferido, pois salva um forke echo -ndeve ser evitado em geral, pois é altamente não transportável.

Adrian Frühwirth
fonte
11
Eu achei o seu ponto de criar o arquivo e, em seguida, usar ferramentas de E / S, muito sólidas. Obrigado.
Pouya
11
@FaheemMitha Sim ( >>). Eu estava me referindo aos exemplos dados pelo OP usando >. Anexar seria inútil se o que você procura é criar arquivos (ou sair NOOP, se existirem).
Adrian Frühwirth
11
Não se esqueça que noclobberisso não deve ser definido para >substituir um arquivo existente.
Ouki
11
@Ouki AFAIK, configuração que não é um comportamento padrão e é possível esquecer que ele é definido em um sistema e não em outro, levando a problemas da mesma maneira que criar uma ideia em alias rm='rm -i'vez de não alias rmi='rm -i'é uma boa idéia.
Agi Hammerthief
11
O @mikeserv, somente > .fileem uma linha de comando, fará isso perfeitamente sem o :.
Charles Duffy
16

A resposta de Adrian Frühwirth está certa. Eu só queria acrescentar que na verdade existe um comando escrito especificamente para criar arquivos: mktemp.

NAME
       mktemp - create a temporary file or directory

SYNOPSIS
       mktemp [OPTION]... [TEMPLATE]

DESCRIPTION
       Create a temporary file or directory, safely, and print its name.  TEM
       PLATE must contain at least 3 consecutive 'X's in last  component.   If
       TEMPLATE is not specified, use tmp.XXXXXXXXXX, and --tmpdir is implied.
       Files are created u+rw, and directories  u+rwx,  minus  umask  restric
       tions.

O trabalho de Granted mktempnão é criar um arquivo com um nome específico, é simplesmente criar um arquivo . No entanto, como você já foi informado, existem muitas maneiras mais eficientes e elegantes de criar arquivos com um determinado nome, que fornecer um comando para isso seria inútil.

Dito isto, você também tem truncatee os fallocatedois cujo objetivo essencial é criar arquivos. Eles simplesmente têm uma abordagem mais sofisticada. Nunca haverá um programa simples que faça o que > filefaz, pois não há como ser melhor do que isso > file.

terdon
fonte
11

A maioria das ferramentas básicas de shell não são projetadas para nenhum propósito muito específico. A maioria das ferramentas básicas de shell são projetadas apenas para interagir com outras pessoas e atingir seu objetivo. Ou talvez deva-se dizer que a maioria das ferramentas faz apenas uma coisa muito básica, independentemente de como elas podem ser combinadas para atingir uma meta.

: >./file

Isso cria um arquivo vazio. Ou trunca um arquivo existente como você deseja. Você pode:

set -o noclobber

para evitar qualquer possibilidade do último caso, a menos que você:

: >|./file

Você pode obter um comportamento semelhante ao touchcom:

: >>./file
: >>|./file

Exceto que :não atualizará o modtime de um arquivo porque ele não é modificado.

DEMO

mkdir test ; cd $_
touch touch.file 
: >null.file
echo >echo.file
ls -l

SAÍDA

-rw-r--r-- 1 mikeserv mikeserv 1 Apr 10 14:52 echo.file
-rw-r--r-- 1 mikeserv mikeserv 0 Apr 10 14:52 null.file
-rw-r--r-- 1 mikeserv mikeserv 0 Apr 10 14:52 touch.file

NÃO TOQUE

: >>|./echo.file
ls -l 

SAÍDA

-rw-r--r-- 1 mikeserv mikeserv 1 Apr 10 14:52 echo.file
-rw-r--r-- 1 mikeserv mikeserv 0 Apr 10 14:52 null.file
-rw-r--r-- 1 mikeserv mikeserv 0 Apr 10 14:52 touch.file
mikeserv
fonte
Por padrão, o eco é adicionado \nno final da linha. Tente echo -n >echo-n.file(tamanho = 0) e echo -e >echo-e.file(tamanho = 1)
Thomas
@Thomas 'Uma string a ser gravada na saída padrão. Se o primeiro operando for -n ou se algum dos operandos contiver um caractere de barra invertida ('\'), os resultados serão definidos pela implementação. Nos sistemas em conformidade com XSI, se o primeiro operando for -n, ele será tratado como uma sequência, não como uma opção. As seguintes sequências de caracteres deve ser reconhecido em sistemas XSI-conformant dentro de qualquer um dos argumentos ...' pubs.opengroup.org/onlinepubs/009604599/utilities/echo.html
mikeserv
Bastante justo, obrigado pelo link, e meu comentário não é o ponto de qualquer maneira
Thomas
2
Sim, de fato e desculpe, eu quis dizer que meu comentário estava faltando o ponto de sua resposta, desculpe por isso.
Thomas
11
Uma ilustração da tendência de generalização do Unix é o fato de o comando para exibir o conteúdo de um arquivo ser chamado cat. Por que ter um comando para exibir um arquivo, quando você pode fazer um comando para concatenar vários arquivos na saída padrão?
200_success
1

O utilitário installfoi projetado para criar arquivos! Você pode transmitir o conteúdo do arquivo via /dev/stdin(na maioria dos casos, no entanto, na maioria dos tipos de Linux, isso requer que /procesteja montado) ou fornecer outro arquivo de origem. Você pode definir a propriedade e as permissões.

echo "New file" | install -o 0644 -m 452452 -g dumbass /dev/stdin /var/www/index.html

como um exemplo bobo.

Otheus
fonte