File mv Linux con nome lungo


19

In Linux a volte rinominare i file in questo modo:

mv dir1/dir2/dir3/file.txt  dir1/dir2/dir3/file.txt.old

Nota che voglio solo rinominare il file, non spostarlo in un'altra directory.

Esiste un comando che mi consentirebbe di eseguire una versione abbreviata di quel comando? Sto pensando a qualcosa del tipo:

mv dir1/dir2/dir3/file.txt  file.txt.old

o forse anche qualcosa del genere (per aggiungere semplicemente al nome):

mv dir1/dir2/dir3/file.txt  {}.old

Il mio obiettivo non è di dover specificare nuovamente il percorso completo.

So che quegli "esempi" che ho scritto non funzionano, ma è solo un'idea di ciò che voglio realizzare.

Non voglio dover accedere alla directory.


8
Perché non passi alla directory? È veloce e risolve il tuo problema.
— Michael Hampton

Ho a che fare con molte sottodirectory da questa stessa posizione, è più lento se devo tornare ogni volta in questa directory dei genitori
— santiago arizti,

3
Nessuno ha detto che dovevi passare a qualche altra directory, solo quella che desideri.
— Michael Hampton

Si noti che (cd dir1/dir2/dir3 && exec mv file.txt{,.old})ha effettivamente le stesse prestazioni del codice senza il sottoprocesso, perché execevita l' fork()ing durante l'invocazione del comando esterno, quindi si ha esattamente un fork in entrambi i modi.
— Charles Duffy,

Risposte:


45

per un singolo file provare

mv dir1/dir2/dir3/file.{txt,txt.old}

dove il X{a,b}costrutto si espande Xa Xb, puoi avere un'anteprima usando

echo dir1/dir2/dir3/file.{txt,txt.old}

per vedere se si adatta alle tue necessità.

Nota:

  1. quello per più file

    mv dir1/dir2/dir3/file{1,2,3}.{txt,txt.old}
    

è improbabile che si espanda a ciò che desideri. (questo si espanderà in un misto di file.txt file1.txt.old file2.txt ...)

  1. {txt,txt.old}può essere protetto {,.old}come da commento

  2. se il nome della directory non è ambiguo, è possibile utilizzare il carattere jolly.

    mv *1/*2/d*/*.{,old}
    

per l'uso di più file rename

rename -n s/txt/old.txt/ dir1/dir2/dir3/file*.txt 

rilasciare -nper avere una rinomina efficace.


1
bello, non conoscevo questo modo di espandersi! grazie
— santiago arizti il

14
Non mv dir1/dir2/dir3/file.txt{,.old}funzionerebbe anche e sarebbe ancora più breve?
— Josh

3
@Josh Sì, funziona perfettamente e richiede meno tasti. Uso questo costrutto molto regolarmente.
— rlf

2
è divertente come puoi usare la shell Linux per anni e trovare ancora nuovi trucchi per tutto il tempo
— santiago arizti

Immagino che tutti quei "trucchi" sarebbero più ovvi se avessi avuto un addestramento formale nella lingua bash, ma ho appena imparato abbastanza per andare d'accordo.
— santiago arizti,

6

Il comando renamerinomina tutti i file corrispondenti. Il suo scopo principale è rinominare più file, ma se l'espressione Perl corrisponde a un solo file, rinominerà solo questo singolo file. Per i dettagli e la sintassi specifica distro si prega di leggere la pagina man: man rename.

Esempio di utilizzo: rinominare "/path/file.txt" in "/path/file.txt.old":

rename 's/file.txt/file.txt.old/g' /path/file.txt

Notazione più breve (grazie a shalomb):

rename 's/$/.old/' /path/file.txt
rename '$_.=".old"' /path/file.txt

Per un funzionamento a secco rename -n.

Ulteriori esempi e dettagli sono disponibili all'indirizzo https://thepcspy.com/read/bulk-rename-files-in-ubuntu/


bene, sapevo del comando di ridenominazione, non sapevo mai tutto ciò che poteva fare, grazie!
— santiago arizti,

6
Sfortunatamente diverse distribuzioni Linux hanno renamecomandi diversi con comportamenti completamente diversi.
— Kasperd,

1
Per questo particolare compito di rinominare aggiungendo .oldal nome del file, è probabilmente un po 'più conveniente fare un rename 's/$/.old/' /path/to/file.txtorename '$_.=".old"' /path/to/file.txt
— shalomb il

@Fabian - Non stavo pignolando, miravo solo alla "mano più corta" per quello che sembra essere un linguaggio di uso frequente che l'OP sta cercando :)
— Shalomb,

4

Per un caso unico, se non voglio cambiare la mia directory corrente potrei semplicemente usare una sotto-shell:

(cd dir1/dir2/dir3/ && mv file.txt file.txt.old)

Poiché tu sei cdall'interno della sotto-shell, non hai cambiato la directory nella tua vera shell


4
Più veloce e più sicuro da usare && exec mv: in questo modo non si tenta di rinominare in caso di cderrore e execconsuma la subshell, evitando così una penalità di prestazione.
— Charles Duffy,

Concordo con il caso && For one-off, come ho detto, non mi preoccuperei del costo della sotto-shell (mantieni la semplicità: essere in grado di ricordare facilmente come farlo è più importante dell'IMO)
— Adam

Direi che se avete intenzione di ricordare un solo modo, ricordando il modo efficiente consente di assicurarsi di non andare il percorso inefficiente nei casi in cui non importa.
— Charles Duffy,

4

Mi piace la soluzione di @ archemar di utilizzare l'espansione {}, perché puoi usarla quando hai già avviato la tua riga di comando. Ecco alcune altre possibilità di completezza:

F="dir1/dir2/dir3/file.txt" ; mv "$F" "$F.old"

(le virgolette sono necessarie solo se nel nome sono presenti spazi o altri caratteri di rottura delle parole)

mymv() {
    mv "$1/$2" "$1/$3"
}

mymv dir1/dir2/dir3 file.txt file.txt.old
mymv dir5/dir6/dir7 file.txt file.txt.old

Appunti:

  • Questa è sintassi bash, potresti usare un'altra shell
  • mymv può essere una stringa ragionevole, ho usato mymv per "la mia mossa".
  • La definizione della funzione può essere inserita nel tuo .bash_profile

Un altro:

cd dir1/dir2/dir3 ; mv file.txt file.txt.old ; cd -

ma

(cd dir1/dir2/dir3/ && exec mv file.txt file.txt.old)

(da @Adam e @CharlesDuffy) è probabilmente migliore nel caso in cui il cd fallisca.


1
Non usare mmv, esiste già un programma chiamato in questo modo.
— glglgl,

1
@glglgl Fatto :)
— Legge 29

2

Se si desidera immettere la sottodirectory per abbreviare il mvcomando, ma si desidera tornare successivamente alla directory corrente, esistono due modi per farlo. Uno è quello di mettere il cde mvin una subshell (come è già stato suggerito).

L'altro è usare pushde popdcambiare directory:

pushd dir1/dir2/dir3/; mv file.txt file.txt.old; popd

Il pushdcomando è simile cd, tranne per il fatto che prima spinge il nome della directory corrente su uno stack. popdrimuove il nome principale dallo stack e passa a quella directory.


pushde popdsono estensioni destinate all'uso interattivo - POSIX le elenca esplicitamente come "i risultati non sono specificati" e una shell creata per l'esecuzione di script (cioè in un ambiente embedded minimo) non deve supportarli.
— Charles Duffy,

2

Vorrei solo fare

cd dir1/dir2/dir3/
mv file.txt file.txt.old
cd ~- # go to the most recent directory

0

La soluzione che coinvolge: mv something{.txt,.txt.old}sta usando un "bashismo". Se vuoi un modo più portatile, usando manipolazioni variabili comuni:

# rename all files "file*.txt" of directory /dir1/dir2/dir3 into file*.txt.old:
for f in dir1/dir2/dir3/file*.txt ; do
  mv "$f" "${f/.txt/.txt.old}"  # note there are no terminating "/"
done


# "${var/A/B}" is the content of var with the first occurence of "A" replaced by "B"

2
Vedere pubs.opengroup.org/onlinepubs/009695399/utilities/… per la specifica POSIX pertinente - ${var/text/replacement}è un bashismo stesso.
— Charles Duffy,

@CharlesDuffy oh ... Mi rendi triste :(
— Olivier Dulac il
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.