Lo spostamento di file con "e * ha causato un errore
Ho problemi con lo spostamento di file in uno script bash. Ho provato diverse soluzioni che ho trovato qui, sullo stesso problema, ma non riesco a trovare nulla che funzioni ..
il mio ultimo tentativo è stato l'aggiunta shopt -s dotglob nullglob
ma non ha risolto nulla ..
In questo test,
jdir0="/media/sf_Mediaserver3/test22/abbamax.(6th.copy)..kansas.(1999)"
mv -v "$jdir0/*" "$jdir0/subs/" &>> $debuglog
.. e ottengo:
mv: cannot stat '/media/sf_Mediaserver3/test22/abbamax.(6th.copy)..kansas.(1999)/*': No such file or directory
ma sì, ci sono!
drwxrwx--- 1 root vboxsf 4096 Aug 22 07:06 ../
-rwxrwx--- 1 root vboxsf 0 Aug 21 17:19 'kallee.(222)..nnn.srt'*
-rwxrwx--- 1 root vboxsf 159363 Aug 21 17:26 'movie.test(2929).ismim.mp4'*
drwxrwx--- 1 root vboxsf 0 Aug 22 07:06 subs/
(il motivo per cui i nomi sono davvero strani è che io prima di questa funzione sto testando per rimuovere i caratteri non validi)
aggiornamento: Apparentemente ho ricevuto errori intermittenti e finalmente dopo giorni l'ho ricondotto al problema del server (dove erano archiviati i file). Apparentemente questi errori si sono verificati se il server non ha terminato il salvataggio / cambio di nome e lo script gli ha chiesto di fare qualcosa di nuovo. Ad esempio, rinominare il file A in B e poi chiedergli di rinominare B in C PRIMA che il server avesse eseguito la prima richiesta, il che ha comportato che il server dicesse: B non esiste, il che ovviamente ha causato un codice di errore.
Risposte
*
è un operatore glob della shell. Deve essere lasciato non citato per essere riconosciuto come tale. Quando citato, /media/sf_Mediaserver3/test22/abbamax.(6th.copy)..kansas.(1999)/*
viene passato letteralmente a mv
e mv
cerca di spostare quel file chiamato *
, ma non esiste un file di questo tipo.
Quindi hai bisogno di:
mv -v -- "$jdir0"/* "$jdir0/subs/" >> "$debuglog" 2>&1
Affinché la shell si espanda "$jdir0"/*
nell'elenco dei file corrispondenti prima di chiamare mv
.
Tu non vuoi nullglob
qui come ciò significherebbe che, in assenza di file corrispondenti che "$jdir0"/*
modello, mv
sarebbe invocata con un solo -v
, --
e media/sf_Mediaserver3/test22/abbamax.(6th.copy)..kansas.(1999)/subs/
causando un errore di sintassi confondere con mv
.
failglob
interrompere il comando quando i glob non corrispondono potrebbe essere un'opzione migliore in quel caso, anche se si noti che in quel caso si bash
interrompe in modo incoerente a seconda del contesto in cui viene invocato il comando, il che rende questa opzione difficile da usare negli script.
dotglob
è consentire ai glob di abbinare i file nascosti.
Ora, nota che i glob corrispondono ai file indipendentemente dal loro tipo¹, in modo che *
anche quelli sopra corrisponderanno subs
. Se subs
è un collegamento simbolico a una directory, mv
sposterà felicemente quel subs
collegamento simbolico in quella directory, causando il fallimento di tutte le mosse successive poiché la subs
directory di destinazione è ora scomparsa. Se subs
è una semplice sottodirectory, mv
probabilmente si lamenterà di non poter spostare una directory in se stessa.
Quindi potresti volerlo scrivere invece:
shopt -s extglob
mv -v -- "$jdir0"/!(subs) "$jdir0/subs/" >> "$debuglog" 2>&1
Dov'è !(pattern)
l'operatore glob esteso ksh che corrisponde a qualsiasi nome di file che non corrisponde pattern
, quindi qui spostando qualsiasi file ma subs
.
Si noti inoltre che nella bash
shell, anche le espansioni dei parametri devono essere quotate quando si trovano obiettivi di reindirizzamento anche in istanze di shell non interattive (tranne quando bash è in modalità POSIX).
¹ a meno che non si utilizzi zsh al posto di bash e dei suoi qualificatori glob come *(.)
per spostare solo i file regolari