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.