Come eseguo i comandi in un'altra cartella, senza ripetere il percorso della cartella?


73

Esiste un modo intelligente per eseguire operazioni di copia e spostamento o un comando per duplicare un file, senza dover fare un cd, quindi mvdopo, nella stessa cartella?

Ad esempio, devo eseguire quanto segue:

mv /folder1/folder2/folder3/file.txt /folder1/folder2/folder3/file-2013.txt

Nota che la directory in cui sto spostando il file è la stessa, ma devo inserire di nuovo l'intero percorso ea volte diventa fastidioso. Sono curioso di sapere se esiste un altro modo per farlo senza dover reinserire l'intero percorso , perché l'operazione verrebbe eseguita nello stesso percorso.


9
Non posso credere che questo abbia tanti voti positivi. È un duplicato unix.stackexchange.com/questions/35782/… e unix.stackexchange.com/questions/66889/…
user13107,

13
@ user13107 Esistono molti modi per porre una domanda, inclusi diversi termini. E se non sai che la risposta si chiama "espansione parentesi", potresti non essere in grado di trovarla immediatamente.
Slhck,

2
@ user13107 si trovano su un sito diverso, quindi non duplicati
user151019,

1
Mark, grazie, non conoscevo quella regola sui duplicati. @slhck Sì. Capisco. Ero solo frustrato perché la mia domanda su Unix.SE è stata chiusa come duplicata e questa è diventata così popolare.
user13107,

3
@ user13107, ecco cosa ottieni pubblicando sul sito giusto
Samuel Edwin Ward,

Risposte:


125

Usa semplicemente l' espansione del controvento :

mv /folder1/folder2/folder3/{file.txt,file-2013.txt}

Ciò equivale a scrivere:

mv /folder1/folder2/folder3/file.txt /folder1/folder2/folder3/file-2013.txt

L'espansione del controvento ti consente di fornire più argomenti, ovviamente. Si può anche passare gamme ad esso, ad esempio per creare un paio di cartelle di prova, è possibile eseguire mkdir test_{a..z}, e partendo da Bash 4, è possibile creare sequenze di zeri e, come in touch foo{0001..3}, che crea foo0001, foo0002e foo0003. Il Wiki di Bash Hackers ha un articolo con un paio di esempi per te.

Se devi usare due comandi diversi, usa prima una subshell e cdlì, come nella risposta di @ Ignacio .


5
Non sapevo bracedell'espansione, grazie!
Valter Silva,

Ci ho provato e sembra non funzionare:meniac ~: mv /tmp/f1/f2/f3/f4/f5/f6/{file.txt, file2.txt} mv: cannot stat ``/tmp/f1/f2/f3/f4/f5/f6/{file.txt,': No such file or directory
Valter Silva,

5
Sei sicuro di usare Bash, come in /bin/bash, e non sei in uno script che ha /bin/shnello shebang o in qualche altra shell che non supporta l'espansione del controvento? Se corri set, SHELLOPTScontengono braceexpand?
Slhck,

22
Nota che non ci dovrebbe essere spazio tra file.txt,e file2.txt.
Slhck,

9
Puoi renderlo ancora più breve, per evitare errori di battitura nella parte che non cambia:mv /folder1/folder2/folder3/file{,-2013}.txt
Jan Fabry,

74

Esegui l'operazione in una subshell.

( cd /folder1/folder2/folder3 && mv file.txt file-2013.txt )

La modifica della directory di lavoro non verrà propagata alla shell padre.


11
+1: Mi piace quello, più portatile attraverso le shell rispetto al trucco di espansione del rinforzo (che è pulito, ma meno portatile)
Olivier Dulac,

@Olivier, cosa ti fa pensare che l'espansione del tutore non sia portatile? Quale shell hai in mente che non la supporta?
alexis,

5
L'espansione del controvento @alexis non è specificata da POSIX, pertanto non è portatile "in base alla progettazione". ash, dash, ksh88Per non parlare del vecchio bourne shell sono esempio di gusci non sostengono.
jlliagre,

@jlliagre Quali delle shell che hai citato sono completamente conformi a POSIX? Ciò significa che non avrebbero alcuna espansione di parentesi graffe anche se fosse POSIX. ksh88 era prima della ratifica di POSIX; dovresti aggiornare ad almeno ksh93. Le uniche due persone su Linux che potrebbero interessare sono ash e dash poiché sono utilizzate in alcune piccole distribuzioni incorporate (busybox, iirc?) E dischi di ripristino.
Kaz,

2
@Kaz Mi interessa la portabilità dei comandi della shell e il fatto che siano interattivi o meno non importa. Certo, sei certamente libero di non preoccupartene, ma per favore accetta che la gente la pensi diversamente. Il fatto che usi sempre bash o una shell che supporti l'espansione barce non significa che sia il caso di tutti.
jlliagre,


11

Puoi impostare una variabile. Naturalmente questo ha l'effetto collaterale di lasciare in giro le variabili.

D=/folder1/folder2/folder3; mv $D/file.txt $D/file-2013.txt

E, naturalmente, puoi evitare l'effetto collaterale di lasciare in giro le variabili mettendo l'intera riga di comando in una subshell: (D="/folder1/folder2/folder3"; mv "$D"/file.txt "$D"/file-2013.txt)o semplicemente aggiungendo un unsetcomando alla fine. (Ho aggiunto le virgolette come "best practice"; se hai l'abitudine di usare sempre le virgolette, non dovrai fermarti e grattarti la testa quando arriva un percorso che contiene caratteri speciali.)
Scott,

@Scott se hai intenzione di usare una subshell per eliminare gli effetti collaterali, è più facile fare una cosa cdche impostare una variabile. Non molto più facile, lo ammetto.
Isaac Rabinovitch

2

Mi piacciono le altre soluzioni, ma eccone un'altra, implementata come uno script con array bash, pushd, popd:

#!/bin/bash
set -e
# from http://stackoverflow.com/a/246128/178651
script_path="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

# paths relative to the script
relative_paths=( \
path1 \
path2 \
path3 \
path4
)

for relative_path in "${relative_paths[@]}"
do
  pushd "$script_path/$relative_path" > /dev/null 2>&1
  pwd
  mv filename1 filename2
  # could do other stuff in this directory...
  popd > /dev/null 2>&1
done

pushd "$script_path" > /dev/null 2>&1
# could do other stuff in same directory as script...
popd > /dev/null 2>&1

1

Slhck risponde direttamente alla domanda nel modo più semplice possibile, ma a Valter piace anche la risposta dell'autopop, quindi eccone una che segue le stesse linee;

pushd /folder1/folder2/folder3/; mv file.txt file-2013.txt; popd
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.