In uno script, se metto #!/bin/bash
in alto, funzionerà bene:
cp directory/{foo,bar} destination
Tuttavia, con sh, questo darà l'errore "nessun file o directory del genere". In sh, c'è un altro modo per raggiungere lo stesso obiettivo finale con un comando?
Risposta accettata:
Come hai osservato, non tutte le shell supportano l'espansione del rinforzo.
Modo 1:due percorsi separati (ovvero, scrivendo il prefisso due volte)
Se il tuo obiettivo è davvero solo quello di farlo in un comando, un modo semplice è:
cp directory/file1 directory/file2 destination
Il cp
comando supporta più argomenti di origine seguiti da un argomento di destinazione. In effetti, questo è ciò che sta accadendo con il comando che funziona per te in Bash. Bash esegue l'espansione delle parentesi, che converte il comando che hai utilizzato in quello mostrato sopra. Cioè, quando esegui cp directory/{file1,file2} destination
in Bash, il cp
il comando non vede mai parentesi graffe.
Un comando del genere è semplice e di facile comprensione. Suggerisco di prenderlo in considerazione.
Modo 2:una variabile per il prefisso
Ma se il tuo obiettivo è evitare di ripetere te stesso, allora potresti preferire non farlo in quel modo, specialmente se directory
in realtà è un lungo percorso. Dopotutto, se devi modificare il percorso più avanti nello script, dovresti apportare modifiche a entrambe le occorrenze.
Puoi memorizzare directory
(o qualsiasi altra cosa, presumibilmente un percorso più lungo) in una variabile di shell:
dir='directory'
cp "$dir/file1" "$dir/file2" destination
$dir
è l'espansione dei parametri. La shell lo sostituisce con il valore contenuto nella variabile dir
. Quando si utilizza l'espansione dei parametri, non si deve omettere le virgolette doppie, tranne nel raro caso in cui si desidera eseguire la divisione dei campi e il globbing. (Questo vale anche per Bash.)
Sono due comandi, ma se il tuo vero obiettivo è evitare di ripeterti, potrebbe essere quello che vuoi. Potresti scrivere
dir='directory'; cp "$dir/file1" "$dir/file2" destination
per renderlo "un comando", ma non è più breve ed è un po' meno leggibile.
(Nota che non puoi semplicemente rimuovere il ;
là. Il risultato dell'esecuzione sarebbe un comando ben formato, ma non farebbe quello che vuoi. Avrebbe eseguito il cp
comando, passando una variabile di ambiente chiamata dir
con il valore directory
nel cp
ambiente del comando. Dal momento che è la shell e non il cp
comando, che espande dir
, questo non funzionerebbe.)
Modo 3:cd
ig al prefisso
Se il tuo script non sta facendo nient'altro dopo aver eseguito questa operazione, o non importa quale sia la directory corrente per i comandi successivi, allora se destination
è un percorso assoluto , puoi usare:
cd directory
cp file1 file2 destination
Ma non lo consiglio per lo script a meno che il tuo script non esegua azioni successive che traggono vantaggio dall'essere eseguito da quella directory, o possa essere scritto in modo più conciso o semplicemente quando vengono eseguiti da quella directory. Tranne quando la directory da cui viene eseguito uno script è significativa ai fini del copione, fare affidamento su di esso può rendere più difficile ragionare sul copione; inoltre, se il cd
il comando riesce ma il cp
comando non riesce, i messaggi di errore risultanti potrebbero non essere completamente illuminati. Cito invece la tecnica di cd
ing nella directory di origine perché è un modello utile per interattivo uso della shell.
(Come ha sottolineato Hannu, puoi racchiudere un numero qualsiasi di comandi insieme all'interno di (
)
per eseguirli in una subshell e modifiche all'ambiente della shell, incluso l'effetto di cd
, non persisterà dopo l'esecuzione del comando. Questa è una tecnica ampiamente utile, ed era un'omissione sostanziale che non l'avessi menzionata. Nota, tuttavia, che ciò non attenua i problemi relativi all'avere un percorso relativo per la destination
.)
Nota che se il cd
comando non riesce, gli altri comandi verranno comunque eseguiti in genere. Questo potrebbe copiare diversi file che non vuoi copiare (se ci sono altri file con lo stesso nome nella directory da cui era in esecuzione lo script) o produrre messaggi di errore confusi. Quindi potresti preferire:
cd directory && cp file1 file2 destination
Il &&
fa sì che il secondo comando venga eseguito solo se il primo comando è riuscito. Si noti che ciò non annulla ancora l'effetto dell'esecuzione del primo comando. Dopo che l'intera operazione è stata eseguita, sarai ancora nella directory
, a meno che tu non l'abbia eseguito in una subshell con (
)
.