Come posso usare i caratteri jolly in stile ms-dos con ls e mv?


9

Ho la sfortuna di venire da un background MS-DOS - ma almeno mi fa apprezzare quanto Linux sia più potente. Ho lavorato per portare il mio Linux-Fu alla pari, ma ci sono un paio di cose che potrebbero essere fatte con DOS che non sono sicuro di come realizzare più facilmente con Linux:

Rinominare più file - Usando due caratteri jolly

c:\> dir

Directory of c:\
    file1.txt
    file2.txt
    file3.txt
    file4.txt

c:\>rename *.txt *.bak

c:\> dir

Directory of c:\
    file1.bak
    file2.bak
    file3.bak
    file4.bak

So che potrei usare find -execqui, ma è possibile usare una sintassi più breve - forse mvcon alcuni flag o sintassi speciali? Immagino che la chiave di questo sia il secondo * carattere jolly poiché Linux non dovrebbe avere problemi con il primo (cioè so come selezionare i file che voglio rinominare usando i caratteri jolly)

Rinominare un singolo file - usando un carattere jolly

c:\> dir

Directory of c:\
    file1.txt

c:\>rename file1.txt *.bak

c:\> dir

Directory of c:\
    file1.bak

Ciò sarebbe particolarmente utile quando si rinomina nomi di file lunghi e ingombranti. Ho pensato che forse avrei potuto usare mv file1.txt $1.bakper finire con file1.txt.bakquale sarebbe anche accettabile, ma non sono sicuro che puoi fare riferimento a un $1parametro inline con un comando shell. Ancora una volta, in questo caso particolare, è solo conveniente il modo in cui ms-dos bastardizza il *carattere jolly da utilizzare come una sorta di corrispondenza cattura / sostituzione per parte del nome file.

Filtro degli elenchi di directory con un carattere jolly

c:\> dir

Directory of c:\
    file1.txt
    file2.txt
    file3.txt
    file4.txt
    text.txt
    \temp       (directory) 

c:\> dir file*

Directory of c:\
    file1.txt
    file2.txt
    file3.txt
    file4.txt

c:\> t*

Directory of c:\
    text.txt
    \temp       (directory) 

Non sono sicuro di quale sia la sintassi giusta per farlo lso se sia persino possibile. Se avessi fatto qualcosa del genere ls t*, sarebbe ricominciato nelle directory a partire da t. La mia soluzione è stata utilizzata find . --max-depth 1 -iname "t*"o qualcosa del genere ls -al | grep t- nessuno dei quali è breve e semplice come dir t*è.

Infine, so di poter impostare gli alias per rendere più brevi questi lunghi comandi, ma mi piacerebbe imparare un po 'di Linux out-of-the-box per fare queste cose perché a volte sei connesso a un sistema remoto o stai lavorando su una nuova macchina.

Quindi, come posso mve lsfile allo stesso modo in cui ho usato dire renamefile?

Risposte:


15

Una delle differenze fondamentali tra cmdshell Windows e POSIX è chi è responsabile delle espansioni di caratteri jolly. Le conchiglie eseguono tutte le espansioni richieste prima di avviare i comandi effettivi richiesti. passa cmd principalmente i motivi jolly ai comandi non modificati. (Dico per lo più, dal momento che penso che ci siano eccezioni e le variabili di ambiente sono espanse nella maggior parte dei casi.) Questo rende la scrittura di un renameche funzionerebbe con la stessa sintassi di quella cmdpiuttosto complicata.

Ma c'è un renameper Linux - con argomenti completamente diversi, controlla la pagina man (che è un po 'concisa sul mio sistema e renameproviene dal util-linuxpacchetto sul mio sistema, che dovrebbe essere ampiamente disponibile). La tua prima ridenominazione verrebbe fatta in questo modo:

rename .txt .bak *.txt

Si noti che la shell esegue l' *espansione, quindi renamein realtà pensa che sia stata invocata in questo modo:

rename .txt .bak file1.txt file2.txt file3.txt ...

Quindi puoi indovinare la versione del singolo file:

rename .txt .bak file1.txt

Se non si desidera utilizzare renamema implementarlo da soli, è possibile creare una funzione per questo. Supponendo che desideri modificare solo l'estensione del file e, per rinominare un singolo file, guarda questo:

$ function chext() {
  newext="$1"
  file="$2"
  newfile="${file%.*}$newext"
  echo mv "$file" "$newfile"
}
$ chext .csv test.txt
mv text.txt text.csv

$newfileviene creato utilizzando una rimozione di sottostringa per rimuovere l'estensione originale, quindi concatena la nuova estensione. È possibile estendere quella funzione per gestire più file in modo relativamente semplice.


Per quanto riguarda la tua lsdomanda, usa l' -dinterruttore. Ciò impedirà lsdi elencare il contenuto delle directory.

demo:

$ ls -al
total 536
drwx------   3 owner users 528384 Jan  7 17:29 .
drwxr-xr-x 126 owner users  12288 Jan  7 17:26 ..
-rw-r--r--   1 owner users      0 Jan  7 17:28 f1.csv
-rw-r--r--   1 owner users      0 Jan  7 17:28 f2.csv
-rw-r--r--   1 owner users      0 Jan  7 17:28 f3.csv
-rw-r--r--   1 owner users      0 Jan  7 17:28 f4.csv
drwxr-xr-x   2 owner users   4096 Jan  7 17:33 test
-rw-r--r--   1 owner users      0 Jan  7 17:27 test.csv

Rinomina jolly

$ rename .csv .txt f*
$ ls -al
total 536
drwx------   3 owner users 528384 Jan  7 17:34 .
drwxr-xr-x 126 owner users  12288 Jan  7 17:26 ..
-rw-r--r--   1 owner users      0 Jan  7 17:28 f1.txt
-rw-r--r--   1 owner users      0 Jan  7 17:28 f2.txt
-rw-r--r--   1 owner users      0 Jan  7 17:28 f3.txt
-rw-r--r--   1 owner users      0 Jan  7 17:28 f4.txt
drwxr-xr-x   2 owner users   4096 Jan  7 17:33 test
-rw-r--r--   1 owner users      0 Jan  7 17:27 test.csv

Rinomina file singolo

$ rename .txt .csv f1.txt 
$ ls -al
total 536
drwx------   3 owner users 528384 Jan  7 17:34 .
drwxr-xr-x 126 owner users  12288 Jan  7 17:26 ..
-rw-r--r--   1 owner users      0 Jan  7 17:28 f1.csv
-rw-r--r--   1 owner users      0 Jan  7 17:28 f2.txt
-rw-r--r--   1 owner users      0 Jan  7 17:28 f3.txt
-rw-r--r--   1 owner users      0 Jan  7 17:28 f4.txt
drwxr-xr-x   2 owner users   4096 Jan  7 17:33 test
-rw-r--r--   1 owner users      0 Jan  7 17:27 test.csv

Il predefinito ls

$ ls -l t*
-rw-r--r-- 1 owner users    0 Jan  7 17:27 test.csv

test:
total 0
-rw-r--r-- 1 owner users 0 Jan  7 17:33 dont_show_me_please

ls che non controlla le directory

$ ls -ld t*
drwxr-xr-x 2 owner users 4096 Jan  7 17:33 test
-rw-r--r-- 1 owner users    0 Jan  7 17:27 test.csv

molto bella! penso di essermi appena spostato su una cintura con il mio Linux-Fu! Grazie!
Cwd,

Suggerimento per avanzare un po 'con questo (ed evitare insidie): usa semplici funzioni o script per vedere cosa succede quando lo fai somefunc *.Extse quel pattern non corrisponde a nessun file e gioca con le citazioni per vedere se riesci a passare un pattern in giro ( senza averlo espanso) tra le funzioni. Consiglio di sicurezza: non usarlo da rmnessuna parte mentre si sperimenta l'espansione di globbing / shell :-)
Mat

4

Una cosa da tenere a mente quando si tratta di caratteri jolly è che sono espansi dalla shell. L'applicazione non sa se hai usato caratteri jolly o digitato i nomi. Ad esempio, se si digita rename *.txt *.bak, il renamecomando visualizza qualcosa di simile rename file1.txt file2.txt existingfile.bak. Non sono abbastanza informazioni per continuare.

Tratterò la domanda per lsprima, perché è più semplice. Se tutto ciò che desideri sono i nomi corrispondenti, non è necessario ls, poiché la shell sta già eseguendo l'espansione.

echo t*

Se vuoi maggiori informazioni sui file, passa l' -dopzione a ls, per dirgli di non elencare il contenuto delle directory.

ls -ld t*

Non esiste un'utilità standard per rinominare i file, perché i primi sistemi unix non ne avevano uno. Il metodo portatile per rinominare i file utilizza un ciclo ed è un po 'dettagliato:

for x in *.txt; do mv -- "$x" "${x%.txt}.bak"; done

Esistono diverse utilità comuni per rinominare i file, nessuna delle quali è garantita l'installazione su un determinato sistema unix, ma sono tutte facili da installare. Ecco i principali:

  • renamedalla util-linuxsuite, disponibile su ogni sistema Linux non incorporato (e da nessun'altra parte). Su Debian e derivati ​​(incluso Ubuntu), questo comando è chiamato rename.ul. A condizione che non vi siano .txtaltre occorrenze oltre l'estensione finale, è possibile scrivere

    rename .txt .bak *.txt
    
  • renameè uno script Perl fornito da Debian e derivati /usr/bin/rename. È possibile rinominare i file secondo i comandi Perl arbitrari.

    rename 's/\.txt\z/\.bak/' *.txt
    
  • mmv, che può rinominare, copiare e collegare i file secondo diversi schemi basati sul nome e ha molte opzioni relative a ciò che accade se esiste già un nome di destinazione. Si noti che è necessario utilizzare le virgolette per proteggere i caratteri jolly dall'espansione della shell.

    mmv '*.txt' '#1.txt'
    
  • zmvè una funzione zsh , disponibile se e solo se la tua shell è zsh. Può corrispondere a schemi zsh arbitrari (quindi puoi abbinare i nomi dei file in base a espressioni regolari arbitrarie, non solo caratteri jolly, e puoi abbinare i file con altri criteri come date e dimensioni). zmvpuò anche copiare e collegare.

    zmv '(*).txt' '$1.txt'
    

Se hai un certo controllo sulle macchine che usi, la mia raccomandazione è di usare zsh come shell (ha altri vantaggi rispetto a bash) e mettere queste righe nel tuo ~/.zshrc:

autoload -U zmv
alias zmv='noglob zmv -w'
alias zcp='zmv -C'
alias zln='zmv -L'
alias zsy='zmv -Ls'

noglobè una funzione zsh che dice alla shell di non espandere i caratteri jolly nell'argomento del comando. In questo modo puoi scrivere zmv *.txt \$1.txt(dovrai sempre proteggere $in un testo sostitutivo).

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.