Perché questo comando xargs non funziona?


14

Volevo eliminare tutte le estensioni .sh così ho fatto questo:

ls *.sh | xargs -I {} mv {} `basename {} .sh`

Tuttavia non funziona, si comporta come basenamerestituisce un nome file invariato.

Perché si sta comportando in quel modo?

Ad esempio, funziona:

ls *.sh | xargs -I {} echo `basename {}.jpg .jpg`;

MODIFICA :

Soluzione: la virgoletta singola impedisce la `basename ...`valutazione da parte della shell prima dell'esecuzione del comando.

ls *.sh | xargs -I {}  sh -c 'mv {} `basename {} .sh`'

Risposte:


12

Perché il comando basename viene eseguito prima dell'esecuzione della pipeline. Per far funzionare tutto ciò è necessario xargs per eseguire basename e puoi farlo con sh -c, ad esempio:

ls *.sh | xargs -L1 sh -c 'basename $1 .sh' dummy

Appunti:

  • Se non dici xargsdove inserire i nomi dei file, questi verranno aggiunti alla fine della riga di comando.
  • Dovresti usare l' -L1opzione o il suo equivalente, quindi xargspassa solo un argomento a sh.
  • L'uso dell'output di lspuò avere effetti indesiderati .

modificare

Rimosse le opzioni obsolete, grazie a TechZilla


3
Il tuo primo punto è errato, a meno che tu non intendessi che è predefinito rispetto -iall'opzione, ma quelle "classiche" sono state deprecate. Ad esempio, per usare solo un'opzione / riga, la nuova pagina man POSIX consiglia -L1. Per chiamare il vecchio comportamento di -i, la pagina consiglia l' -I'{}'opzione.
JM Becker,

Quindi, in realtà riguarda i simboli "" anziché "". Suppongo che 'impedisce la valutazione della shell di' '. Vedi le mie modifiche.
Majkinetor,

@TechZilla: grazie per le correzioni. @majkinetor: sì e no, devi ritardare la valutazione, ma non credo che tu possa usare i backtick (`).
Thor,

1
@majkinetor: ah, capisco cosa intendi ora. Per rinominare i file in questo modo avrei preferito usare rename, ad esempio: rename 's/\.sh//' *.sh. Prova prima con dry-run ( -n).
Thor,

1
@majkinetor: renamefunziona benissimo e abbastanza semplice, ma ricorda che è molto specifico per la distribuzione. Le distribuzioni basate su RHEL e Debian forniscono renamecomandi diversi , quindi bisogna tenerlo presente quando si creano script cross-distro.
JM Becker,

4

Non sono sicuro della tua domanda, stai davvero chiedendo perché la tua prima riga non funziona? O stai cercando un metodo adeguato per rinominare tutti i file .sh?

Supponendo che sia il metodo più pulito, preferisco preparare prima le opzioni di comando xargs. Per rimuovere un'estensione di file .sh, considero spesso questo approccio,

 find -maxdepth 1 -type f -iname '*.sh'  | sed 'p;s_.sh$__' | xargs -L2 mv
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.