Dividi un file per linea e controlla l'estensione dei file risultanti


28

Esiste un comando standard per la divisione dei file - split.

Ad esempio, se voglio dividere un file di parole in più blocchi di 10000 righe, posso usare:

split -dl 10000 words wrd

e genererebbe diversi file nei formati wrd.01, wrd.02 e così via.

Ma voglio avere un'estensione specifica per quei file - ad esempio, voglio ottenere i file wtd.01.txt, wrd.02.txt.

C'è un modo per farlo?

Risposte:


12

Non con split, ma puoi facilmente rinominarli in seguito, oppure puoi farlo in awk:

awk '{filename = "wrd." int((NR-1)/10000) ".txt"; print >> filename}' inputfile

Sembra buono, ma non funziona. Nel tuo modulo, si lamenta di "espressione per il reindirizzamento` >> 'ha valore stringa nullo "e se" file "è" modificato "in" nome file ", genera i file del modulo wrd. {Numero file}. {Numero riga} .txt (molti di loro :)
Rogach,

@Rogach Siamo spiacenti, non l'avevo testato, quindi ho dimenticato che awk non esegue la divisione intera. Ho provato questo.
Kevin,

49

Questo non era disponibile allora, ma con versioni più recenti ( ≥ 8.16) di gnu splituno è possibile utilizzare l' --additional-suffixopzione per avere il controllo sull'estensione risultante. Da man split:

--additional-suffix=SUFFIX
              append an additional SUFFIX to file names.

quindi quando si utilizza quell'opzione:

split -dl 10000 --additional-suffix=.txt words wrd

i pezzi risultanti finiranno automaticamente in .txt:

wrd00.txt
wrd01.txt
.........

3
Non funziona su mac
ericgu il

2
Adoro il tuo sarcasmo. Sono un unix n00b dal mondo Apple. Sto usando OS X Yosemite e non volevo che altri si schiantassero e bruciassero come ho fatto io. Ho testato e recensito i documenti e non abbiamo questo parametro. Potrei essermi perso qualcosa. developer.apple.com/library/mac/documentation/Darwin/Reference/…
ericgu,

5
@swiftshokunin - la mia risposta riguarda gnu split, parte di gnu coreutils. È disponibile anche su OSX se si installa coreutilstramite homebrewma si noti che per impostazione predefinita, su OSX, le gnuutilità hanno una ganteposta al loro nome (ad esempio gstatinvece di stat) in modo da invocarlo come gsplit(o modificare il PERCORSO come da guida qui se si desidera per usarlo come splitsu OSX split). HTH.
don_crissti,

1
Bella risposta. su OS X, usare gsplitper far funzionare i suffissi numerici (-d).
Brent Faust,

1
caspita, non avevo idea che ci fosse gsplit - probabilmente dai coreutils menzionati sopra e ha - suffisso-aggiuntivo. Grazie a tutti coloro che hanno commentato questa soluzione :)
Łukasz Rysiak

13

Tali attività sono gestite al meglio con la shell. Usa split e quindi scrivi un semplice ciclo per rinominare i file. Per esempio

for file in wrd.*
do
    mv "$file" "$file.txt"
done

rinominerebbe i tuoi file wrd.01, wrd.02, ecc. in modo che abbiano tutti un'estensione .txt.


È abbastanza ovvio, ma spezzerebbe la concisione della sceneggiatura di Bash.
Rogach,

1
La filosofia di Unix è quella di fornire un set di strumenti semplici da combinare per fare un lavoro. La "concisione dello script bash" non era un requisito dichiarato nella tua domanda.
Kyle Jones,

7
PS: la split+mvcombo è più di 6 volte più veloce di awk(circa 3s contro 18s ) per un file di input di 10 milioni di righe (75 MB) ... il testo in ogni riga era il suo numero di riga ... Grazie per aver ribadito il "ovvio" :)
Peter.O

3
PPS: Ho appena verificato un po 'di più. La differenza di velocità è correlata al numero di file creati rispetto al numero di calcoli di formattazione e aritmetici che awk esegue per ciascuna riga indipendentemente dal numero di file di output ... Utilizzando lo stesso file di input dell'esempio precedente: Quando ci sono 100 volte meno file, split + mvè 75 volte più veloce di awk: quando ci sono 100 volte più file, split + mvè 1,5 volte più veloce di awk. Quindi, per me, questo split + mvmetodo vince a mani basse. È come consice (probabilmente moreso), ed è più veloce di awk.
Peter

1
se sei preoccupato che sia lungo 5 righe, prova invece: for file in wrd.*; do mv "$file" "$file.txt"; done:)
Tony,
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.