Comment puis-je utiliser les caractères generics ms-dos avec ls et mv?

J'ai le malheur de venir d'un fond MS-DOS – mais au less ça me fait apprécier combien Linux est plus puissant. Je travaille sur l'obtention de mon Linux-Fu, mais il y a quelques choses qui pourraient être faites avec DOS que je ne suis pas sûr de savoir comment accomplir le plus facilement avec Linux:

Renommer plusieurs files – Utiliser deux caractères generics

c:\> dir Directory of c:\ file1.txt file2.txt file3.txt file4.txt c:\>rename *.txt *.bak c:\> dir Directory of c:\ file1.bak file2.bak file3.bak file4.bak 

Je sais que je pourrais utiliser find -exec ici mais il est possible d'utiliser une syntaxe plus courte – peut-être mv avec quelques drapeaux spéciaux ou la syntaxe? Je suppose que la key de ceci est le deuxième * caractère générique car linux ne devrait pas avoir de problème avec le premier (ie je sais comment sélectionner les files que je veux renommer en utilisant des caractères generics)

Renommer un seul file – Utiliser un caractère générique

 c:\> dir Directory of c:\ file1.txt c:\>rename file1.txt *.bak c:\> dir Directory of c:\ file1.bak 

Cela serait particulièrement utile pour renommer des noms de files longs et difficiles à manipuler. Je pensais que je pourrais peut-être utiliser mv file1.txt $1.bak pour finir avec file1.txt.bak ce qui serait également acceptable mais je ne suis pas sûr que vous pouvez referencer le paramètre $1 inline avec une command shell. Encore une fois, dans ce cas particulier, il est commode de savoir comment ms-dos bastardise le * joker à utiliser comme une sorte de capture / rlocation de correspondance pour une partie du nom de file.

Filtrage des lists d'annuaires avec un caractère générique

 c:\> dir Directory of c:\ file1.txt file2.txt file3.txt file4.txt text.txt \temp (directory) c:\> dir file* Directory of c:\ file1.txt file2.txt file3.txt file4.txt c:\> t* Directory of c:\ text.txt \temp (directory) 

Je ne suis pas sûr de savoir quelle est la bonne syntaxe pour faire cela avec ls , ou si c'est possible. Si je faisais quelque chose comme ls t* il récursif dans les directorys commençant par t . Ma solution de contournement a été soit en utilisant find . --max-depth 1 -iname "t*" find . --max-depth 1 -iname "t*" ou quelque chose comme ls -al | grep t ls -al | grep t – qui ne sont ni aussi courts ni aussi simples que dir t* .

Enfin, je sais que je peux mettre en place des alias pour raccourcir ces longues commands, mais j'aimerais apprendre un peu de linux-fu pour faire ces choses parce que parfois vous êtes connecté à un système distant ou travaillez sur une nouvelle machine.

Alors, comment puis-je mv et ls files de la même manière que j'ai l'habitude de dir et rename files?

L'une des différences fondamentales entre les shells Windows cmd et POSIX est de savoir qui est responsable des expansions generics. Les shells font toutes les extensions requirejses avant de commencer les commands réelles que vous avez demandées. cmd transmet principalement les templates generics aux commands non modifiées. (Je dis surtout, car je pense qu'il y a des exceptions, et les variables d'environnement sont étendues dans la plupart des cas). Cela rend l'écriture d'un rename qui fonctionnerait avec la même syntaxe que dans cmd assez difficile.

Mais il y a un rename pour Linux – avec des arguments complètement différents, consultez la page man (qui est un peu concis sur mon système, et rename vient du package util-linux sur mon système, qui devrait être largement disponible). Votre premier changement de nom serait fait comme ceci:

 rename .txt .bak *.txt 

Notez que le shell fait l'extension * , alors rename lui-même pense qu'il a été appelé comme ceci:

 rename .txt .bak file1.txt file2.txt file3.txt ... 

Ainsi, vous pouvez deviner la version de file unique:

 rename .txt .bak file1.txt 

Si vous ne souhaitez pas utiliser le rename mais que vous l'implémentez vous-même, vous pouvez créer une fonction pour cela. En supposant que vous souhaitez uniquement modifier l'extension de file, et pour le renommage d'un seul file, regardez ceci:

 $ function chext() { newext="$1" file="$2" newfile="${file%.*}$newext" echo mv "$file" "$newfile" } $ chext .csv test.txt mv text.txt text.csv 

$newfile est construit en utilisant une suppression de sous – string pour supprimer l'extension d'origine, puis concatène la nouvelle extension. Vous pouvez étendre cette fonction pour gérer plusieurs files relativement facilement.


Pour ce qui est de votre question, utilisez le commutateur -d . Cela empêchera ls de listr le contenu des directorys.

Démo:

 $ ls -al total 536 drwx------ 3 owner users 528384 Jan 7 17:29 . drwxr-xr-x 126 owner users 12288 Jan 7 17:26 .. -rw-r--r-- 1 owner users 0 Jan 7 17:28 f1.csv -rw-r--r-- 1 owner users 0 Jan 7 17:28 f2.csv -rw-r--r-- 1 owner users 0 Jan 7 17:28 f3.csv -rw-r--r-- 1 owner users 0 Jan 7 17:28 f4.csv drwxr-xr-x 2 owner users 4096 Jan 7 17:33 test -rw-r--r-- 1 owner users 0 Jan 7 17:27 test.csv 

Renommer par un caractère générique

 $ rename .csv .txt f* $ ls -al total 536 drwx------ 3 owner users 528384 Jan 7 17:34 . drwxr-xr-x 126 owner users 12288 Jan 7 17:26 .. -rw-r--r-- 1 owner users 0 Jan 7 17:28 f1.txt -rw-r--r-- 1 owner users 0 Jan 7 17:28 f2.txt -rw-r--r-- 1 owner users 0 Jan 7 17:28 f3.txt -rw-r--r-- 1 owner users 0 Jan 7 17:28 f4.txt drwxr-xr-x 2 owner users 4096 Jan 7 17:33 test -rw-r--r-- 1 owner users 0 Jan 7 17:27 test.csv 

Renommer un file unique

 $ rename .txt .csv f1.txt $ ls -al total 536 drwx------ 3 owner users 528384 Jan 7 17:34 . drwxr-xr-x 126 owner users 12288 Jan 7 17:26 .. -rw-r--r-- 1 owner users 0 Jan 7 17:28 f1.csv -rw-r--r-- 1 owner users 0 Jan 7 17:28 f2.txt -rw-r--r-- 1 owner users 0 Jan 7 17:28 f3.txt -rw-r--r-- 1 owner users 0 Jan 7 17:28 f4.txt drwxr-xr-x 2 owner users 4096 Jan 7 17:33 test -rw-r--r-- 1 owner users 0 Jan 7 17:27 test.csv 

La valeur par défaut ls

 $ ls -lt* -rw-r--r-- 1 owner users 0 Jan 7 17:27 test.csv test: total 0 -rw-r--r-- 1 owner users 0 Jan 7 17:33 dont_show_me_please 

Ce n'est pas inspecter les directorys

 $ ls -ld t* drwxr-xr-x 2 owner users 4096 Jan 7 17:33 test -rw-r--r-- 1 owner users 0 Jan 7 17:27 test.csv 

Une chose à garder à l'esprit quand il s'agit de jokers, c'est qu'ils sont étendus par le shell. L'application ne sait pas si vous avez utilisé des caractères generics ou tapé les noms. Par exemple, si vous tapez rename *.txt *.bak , la command rename voit quelque chose comme rename file1.txt file2.txt existingfile.bak . Ce n'est pas assez d'informations pour continuer.

Je vais d'abord répondre à la question sur ls , parce que c'est plus simple. Si vous ne voulez que les noms correspondants, vous n'avez pas besoin de ls , car le shell est déjà en train de faire l'extension.

 echo t* 

Si vous voulez plus d'informations sur les files, passez l'option -d à ls pour lui indiquer de ne pas listr le contenu des directorys.

 ls -ld t* 

Il n'y a pas d'utilitaire standard pour renommer des files, car les premiers systèmes unix n'en sont pas équipés. La méthode portable pour renommer les files utilise une boucle et est un peu verbeuse:

 for x in *.txt; do mv -- "$x" "${x%.txt}.bak"; done 

Il existe plusieurs utilitaires courants pour renommer des files, dont aucun n'est garanti pour être installé sur un système Unix donné, mais qui sont tous faciles à installer. Voici les principaux:

  • rename de la suite util-linux , disponible sur chaque système Linux non embarqué (et nulle part ailleurs). Sur Debian et les dérivés (y compris Ubuntu), cette command s'appelle rename.ul . Pourvu qu'il n'y ait aucune occurrence de .txt autre que l'extension finale, vous pouvez écrire

     rename .txt .bak *.txt 
  • rename est un script Perl que Debian et les dérivés expédient sous /usr/bin/rename . Vous pouvez renommer des files en fonction de commands Perl arbitraires.

     rename 's/\.txt\z/\.bak/' *.txt 
  • mmv , qui peut renommer, copyr et lier des files en fonction de plusieurs templates basés sur le nom et qui possède de nombreuses options relatives à ce qui se passe si un nom cible existe déjà. Notez que vous devez utiliser des guillemets pour protéger les caractères generics de l'expansion par le shell.

     mmv '*.txt' '#1.txt' 
  • zmv est une fonction zsh , disponible si et seulement si votre shell est zsh. Il peut correspondre à des motifs zsh arbitraires (vous pouvez donc faire correspondre les noms de files selon des expressions régulières arbitraires, et non pas uniquement des caractères generics, et vous pouvez faire correspondre les files à d'autres critères tels que les dates et les tailles). zmv peut également copyr et lier.

     zmv '(*).txt' '$1.txt' 

Si vous avez un certain contrôle sur les machines que vous utilisez, je recommand d'utiliser zsh comme shell (il a d'autres avantages par rapport à bash) et de mettre ces lignes dans votre ~/.zshrc :

 autoload -U zmv alias zmv='noglob zmv -w' alias zcp='zmv -C' alias zln='zmv -L' alias zsy='zmv -Ls' 

noglob est une fonctionnalité zsh qui indique au shell de ne pas développer de caractères generics dans l'argument de la command. De cette façon, vous pouvez écrire zmv *.txt \$1.txt (vous aurez toujours besoin de protéger le $ dans un text de rlocation).