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.