web-dev-qa-db-fra.com

utilisation des caractères génériques linux en cp et mv

Je compose un script pour traiter 20 fichiers. Tous situés dans des répertoires différents. J'ai un nom de fichier partiel.

  1. Dans le répertoire des journaux, File1_Date_time.err change en File1__Date_time_orig.err
  2. cd ../scripts/
  3. sh File.sh

Le répertoire File1 est /data/data1directory/Sample_File1/logs/File1_Data_time.err
Le répertoire File2 est /data/data2directory/Sample_File2/logs/File2_Data_time.err
.....

Mon script ressemble à ceci. (runrunrun.sh)

#!/bin/bash
INPUT=$1
mv /data/*/Sample_*/logs/*_Data_time.err /data/*/Sample_*/logs/*_Data_time_orig.err
cp /data/*/Sample_*/scripts/*.sh /data/*/Sample_*/scripts/*_orig.sh
sh /data/*/Sample_*/scripts/*_orig.sh

En l'exécutant, j'ai essayé.
./ runrunrun.sh File1
. runrunrun.sh File1
sh runrunrun.sh File1

mv: ne peut pas bouger /data/data1directory/Sample_File1/logs/File1_Data_time.err /data/*/Sample_*/logs/*_Data_time_orig.err: Aucun fichier ou répertoire de ce type n'a également reçu des commentaires similaires

Suis-je en train de le faire correctement?

Merci!

10
TJ Wu

Parlons du fonctionnement des caractères génériques pendant une minute.

cp *.txt foo

n'invoque pas réellement cp avec un argument *.txt, s'il existe des fichiers correspondant à ce glob. Au lieu de cela, il exécute quelque chose comme ceci:

cp a.txt b.txt c.txt foo

De même, quelque chose comme

mv *.txt *.old

... ne peut pas savoir quoi faire, car lorsqu'il est invoqué, ce qu'il voit est:

mv a.txt b.txt c.txt *.old

ou, pire, si vous avez déjà un fichier nommé z.old, il verra:

mv a.txt b.txt c.txt z.old

Ainsi, vous devez utiliser différents outils. Considérer:

# REPLACES: mv /data/*/Sample_*/logs/*_Data_time.err /data/*/Sample_*/logs/*_Data_time_orig.err
for f in /data/*/Sample_*/logs/*_Data_time.err; do
  mv "$f" "${f%_Data_time.err}_Data_time_orig.err"
done

# REPLACES: cp /data/*/Sample_*/scripts/*.sh /data/*/Sample_*/scripts/*_orig.sh
for f in /data/*/Sample_*/scripts/*.sh; do
  cp "$f" "${f%.sh}_orig.sh"
done

# REPLACES: sh /data/*/Sample_*/scripts/*_orig.sh
for f in /data/*/Sample_*/scripts/*_orig.sh; do
  if [[ -e "$f" ]]; then
    # honor the script's Shebang and let it choose an interpreter to use
    "$f"
  else
    # script is not executable, assume POSIX sh (not bash, ksh, etc)
    sh "$f"
  fi
done

Cela utilise un expansion des paramètres pour supprimer l'extrémité arrière de l'ancien nom avant d'ajouter le nouveau nom.

17
Charles Duffy

La commande find peut être utilisée de manière assez concise dans les cas simples où vous souhaitez effectuer des opérations sur des correspondances de nom de fichier génériques (ou plus complexes). La technique ci-dessous peut être mémorisée ... presque!

Cela fonctionne en laissant la commande find exécuter une autre commande sur chaque nom de fichier trouvé. Vous pouvez exécuter cet exemple à sec en utilisant echo au lieu de mv.

Si nous voulions déplacer tous les fichiers du répertoire courant avec le nom commençant par 'report', vers un autre répertoire parallèle appelé 'reports':

find . -name "report*.*" -exec mv '{}' ../reports/ \;

La chaîne générique doit être entre guillemets, le {} marquant le nom de fichier qui a été 'trouvé' doit être entre guillemets et le point-virgule final doit être échappé - tout cela en raison du traitement Bash/Shell de ces caractères.

Regardez la page de manuel pour find pour plus d'utilisations: https://linux.die.net/man/1/find

8
MikeW

C'est ce que j'utilise, très rapide à écrire et à mémoriser

Pour copier:

ls -1 *.txt | xargs -L1 -I{} cp {} {}.old 

Pour se déplacer:

ls -1 *.txt | xargs -L1 -I{} mv {} {}.old 

l'explication:

xargs(1) -L1 -I{}  

construire et exécuter des lignes de commande à partir de l'entrée standard

-L max-lines
       Use  at most max-lines nonblank input lines per command line.  Trailing blanks cause an input line
       to be logically continued on the next input line.  Implies -x.

-I replace-str
       Replace occurrences of replace-str in the initial-arguments with names read from  standard  input.
       Also,  unquoted  blanks  do  not  terminate  input  items;  instead  the  separator is the newline
       character.  Implies -x and -L 1.

Fondamentalement avec -L1 il envoie les arguments par un, et -I{} fait du {} le espace réservé

0
Eduard Florinescu

Essaye ça:

Modifiez-les:

zc_cd_delim_01.csv
zc_cd_delim_04.csv

dans ceux-ci:

zc_cd_delim_113_01.csv
zc_cd_delim_113_04.csv

ligne de commande:

for f in zc_cd_delim_??.csv; do var1=${f%%??.*}; 
    mv $f "${var1}113_${f#$var1}"; 
done
0
Jon Lancelle