Aggiungi una nuova riga in un nome file con `mv`


11

È una domanda seria. Ho testato alcuni awkscript e ho bisogno di file con una nuova riga nei loro nomi.


È possibile aggiungere una nuova riga in un nome file con mv?

Ora posso farlo con touch:

touch "foo
bar"

Con il tocco ho aggiunto il carattere di nuova riga per copia e incolla. Ma non riesco a scrivere fooReturnbarnella mia shell.

Come posso rinominare un file, per avere una nuova riga nel nome del file?


Modifica 28/06/2015; 07:08 pm

Per aggiungere una nuova riga in zshposso usare, Alt+Return


2
Perché lo chiedi? Stai scherzando o scherzando con un amico?
Basile Starynkevitch,

2
Non rimuovere la domanda, è utile. Ma evita davvero il più possibile nuove righe nei nomi dei file.
Basile Starynkevitch,

2
Cosa ti fa pensare che farlo con mvsarebbe diverso dal farlo con touch? Hai provato la stessa cosa?
Kevin,

2
Bene, puoi copiare e incollare nel mvcomando con la stessa facilità touch.
Kevin,

2
Quindi lascia che ti suggerisca di formulare più chiaramente il tuo OP: All'interno di un dato ambiente shell non posso digitare una nuova riga all'interno di una stringa tra virgolette come nell'eco "a [return] b".
dan

Risposte:


22

È una cattiva idea (avere strani personaggi nei nomi dei file) ma potresti farlo

 mv somefile.txt "foo
 bar"

(avresti potuto anche fare mv somefile.txt "$(printf "foo\nbar")"o mv somefile.txt foo$'\n'bar, ecc ... i dettagli sono specifici per la tua shell. Sto usando zsh)

Maggiori informazioni sul globbing , ad es. Glob (7) . I dettagli potrebbero essere specifici della shell. Ma capire che /bin/mv è dato (dalla shell), via execve (2) , un espanso matrice di argomenti: espansione argomento e glob è la responsabilità del guscio chiamante.

E potresti persino programmare un minuscolo programma C per fare lo stesso:

#include <stdio.h>
#include <stdlib.h>
int main() {
  if (rename ("somefile.txt", "foo\nbar")) {
     perror("rename somefile.txt");
     exit(EXIT_FAILURE);
  };
  return 0;
}

Salvare sopra il programma in foo.c, compilarlo con gcc -Wall foo.c -o foo quindi eseguire./foo

Allo stesso modo, potresti codificare uno script simile in Perl, Ruby, Python, Ocaml, ecc ...

Ma questa è una cattiva idea. Evita le nuove righe nei nomi dei file (confonderà l'utente e potrebbe spezzare molti script).

In realtà, consiglio anche di usare solo lettere, cifre e +-/._% caratteri non accentati ( / essendo il separatore di directory) nei percorsi dei file. I file "nascosti" (a partire da .) devono essere usati con cautela e parcimonio. Credo che usare qualsiasi tipo di spazio nel nome di un file sia un errore. Utilizzare invece un trattino basso (ad es. foo/bar_bee1.txt) O un segno meno (ad es. foo/bar-bee1.txt)


Sì, lo so, che posso copiare e incollare un carattere di nuova riga, ma come potrei farlo senza copiare e incollare?
AB,

4
Non c'è nessuna copia o incolla qui. C'è una nuova riga digitata dopo foo.
dan

Tuttavia funziona anche incollandolo
kos

1
È una cattiva idea per i soliti file, ma un buon caso di test, come menzionato dall'OP.
artdanil,

5
@e ,sarebbe più innocuo di -(come nella prima posizione) o %. Tutte queste raccomandazioni sono principalmente per aggirare i bug in alcune applicazioni (che si rompono su nomi di file che sono altrimenti validi dal punto di vista del sistema operativo). È arretrato chiedere alle persone di non usare quei personaggi piuttosto che correggere i loro bug.
Stéphane Chazelas,


6

So che hai chiesto una mvsoluzione, tuttavia, nonostante l'avvertimento, questo può essere fatto facilmente con rename(nel pacchetto Perl):

~/tmp$ touch foo
~/tmp$ rename 's/$/\nbar/' foo
Unsuccessful stat on filename containing newline at /usr/share/perl5/File/Rename.pm line 69.
~/tmp$ ls
foo?bar

Grazie per la rename, un'ottima idea. +1
AB,

5

Un aspetto di questo problema non riguarda davvero awk- e solo un po 'della shell. Il problema è che su una tty standard e canonica la maggior parte delle volte la disciplina tty del kernel sta bufferizzando il tuo input - facendo semplicemente eco al tuo schermo e in nessun altro luogo - in modo che possa gestire efficacemente il backspacing e simili.

Tuttavia, quando si preme return o si immette in altro modo una nuova riga, tutti i dati bufferizzati vengono inviati immediatamente all'applicazione di lettura, in genere la shell. Puoi osservarlo osservando $PS2dopo aver inserito una citazione penzolante. Quando la shell stampa $PS2è perché ha appena letto un blocco del tuo input e non è ancora convinto che tu abbia finito.

Quindi, per comodità, ciò di cui hai bisogno è un modo per inviare una \newline nel buffer dei terminali senza dover inviare immediatamente tutti gli altri input. Il modo standard per farlo è w / la sequenza di tasti CTRL+V- che cita per il terminale il tuo prossimo carattere di input. Fai CTRL+Vquindi CTRL+J- perché quest'ultimo è di solito come digitare una \newline letterale . Saprai che ha funzionato quando non lo vedi $PS2perché la shell non ha ancora letto i tuoi input.

Nota però che quando si fa leggere che inserire il precedente CTRL+Vavrà fatto alcuna differenza per la shell a tutti - che cita solo per la linea-disciplina. Avrai sicuramente bisogno di citare la newline e di fare qualcosa di significativo con essa.

A proposito, CTRL+Vpuò essere utilmente applicato in altri modi - per esempio "$(printf \\33)"non è l'unico modo per scrivere un ESCpersonaggio in uno script di shell - e non è nemmeno il più semplice. Puoi letteralmente inserire qualsiasi carattere che la tua tastiera invierà senza che il driver di input tenti di interpretarlo se lo scappi per la prima volta in questo modo.

Mi piace spesso usare <tab> s dalla riga di comando senza che la shell tenti di completare nulla. Poiché le shell che eseguono il completamento in genere configurano <tab> in qualche modo stty eol \t, per far funzionare i loro sistemi di completamento, CTRL+Vfunziona anche per me in ambienti non familiari.


2
Grazie per aver menzionato "Ctrl + V". Stavo per pubblicare una risposta a riguardo e poi ho visto la tua spiegazione.
artdanil,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.