Je fais des trucs avec des fichiers audio, la plupart mais pas tous des fichiers mp3. Maintenant, je veux exécuter certaines commandes uniquement sur les fichiers qui ne sont pas des fichiers mp3, ou uniquement ceux qui n'ont pas de .mp3
extension.
Je me considère assez bon pour les expressions régulières, mais pas tant pour la globalisation de fichiers, qui est subtilement différente de manière inattendue.
J'ai regardé autour de moi et j'ai appris des autres SO & SE répond que Bash a "étendu le globbing" qui me permet de faire ceci:
file ../foo/bar/*.!(mp3)
Mais certains de mes noms de fichiers contiennent des points en plus de celui formant l'extension du nom de fichier:
../foo/bar/Naked_Scientists_Show_19.10.15.mp3
../foo/bar/YWCS_ep504-111519-pt1_5ej4_41cc9320.mp3_42827d48daefaa81ec09202e67fa8461_24419113.mp3
../foo/bar/eLife_Podcast_19.09.26.mp3
../foo/bar/gdn.sci.080428.bg.science_weekly.mp3
Il semble que le glob corresponde à partir du premier point, plutôt qu'à partir du dernier point. J'ai regardé la documentation mais il semble qu'ils soient beaucoup moins puissants que les regex. Mais je n'ai pas vraiment tout gâché car je ne passe pas beaucoup de temps sur les shells * nix.
Ai-je raté un moyen de pouvoir encore le faire avec la globalisation Bash? Sinon, un moyen de réaliser la même chose avec find ou un autre outil vaut toujours la peine d'être connu.
*.!(mp3)
correspond à foo.bar.mp3
car c'est foo.
suivi de bar.mp3
qui est qui n'est pas mp3
.
Vous voulez !(*.mp3)
ici, qui correspond à tout ce qui ne se termine pas par .mp3
.
Si vous souhaitez faire correspondre des fichiers dont le nom contient au moins un .
(Autre qu'un premier qui en ferait un fichier masqué) mais ne se termine pas par .mp3
, Vous pouvez faire !(*.mp3|!(*.*))
.
Il y a aussi la variable GLOBIGNORE
:
La variable
GLOBIGNORE
Shell peut être utilisée pour restreindre l'ensemble de noms de fichiers correspondant à un modèle. SiGLOBIGNORE
est défini, chaque nom de fichier correspondant qui correspond également à l'un des modèles deGLOBIGNORE
est supprimé de la liste des correspondances. Si l'optionnocaseglob
est définie, la correspondance avec les modèles dansGLOBIGNORE
est effectuée sans tenir compte de la casse. Les noms de fichiers.
et..
sont toujours ignorés lorsqueGLOBIGNORE
est défini et non null. Cependant, la définition deGLOBIGNORE
sur une valeur non nulle a pour effet d'activer l'optiondotglob
Shell, donc tous les autres noms de fichiers commençant par ".
’Correspondra. Pour obtenir l'ancien comportement consistant à ignorer les noms de fichiers commençant par ".
', faire '.*
’L'un des modèles deGLOBIGNORE
. L'optiondotglob
est désactivée lorsqueGLOBIGNORE
n'est pas définie.
$ touch a.b.mp3 .c.mp3 foo.tgz .bar
$ echo *
a.b.mp3 foo.tgz
$ shopt -s extglob; echo *.!(mp3)
a.b.mp3 foo.tgz
$ GLOBIGNORE='*.mp3'; echo *
.bar foo.tgz
la façon la plus simple à laquelle je peux penser:
find ${path-to-folder} -type f | grep -vE ".*\.mp3$"
Vous trouvez tous les fichiers dans un dossier et le redirigez vers une grep étendue inversée:
Trouver tous les fichiers dans un emplacement
find ${path-to-folder} -type f
Inverser grep et utiliser une expression régulière pour filtrer par extension
grep -vE ".*\.mp3$"
Drapeaux Grep:
-v
grep inverse
-E
grep étendu (utilisation de l'expression régulière)
Regex a expliqué:
.*
signifie de 0 à n'importe quel nombre de caractères, tout caractère possible
\.
recherche le point réel
mp3
pour la chaîne qui forme l'extension
$
signifie EOL
Peut-être pas idéal pour votre situation, mais je me demandais comment créer une fonction en pur Bash
puis passer l'extension en argument, ce qui peut être pratique si vous voulez l'ajouter dans votre bashrc
et vous voulez faire la même chose à l'avenir, comme ce qui suit
Donc, fondamentalement, ce que nous faisons est le contrôle regex de votre extension souhaitée.
for file in *; do
if [[ $file =~ \.mp3$ ]]; then
echo $file
fi
done
L'implémenter dans une fonction: Cela produirait tous les fichiers avec une extension spécifique dans votre répertoire actuel.
getFileByExt(){
local extension="$1"
if (( $# == 1 )); then
for file in *; do
if [[ $file =~ \.$extension$ ]]; then
echo $file
fi
done
else
echo "Usage: ${FUNCNAME[0]} <extension>"
## If run from bashrc, return the name of function
fi
}
Maintenant, par exemple pour obtenir tous les fichiers avec mp3
extension, ce serait aussi simple que de faire:
getFileByExt mp3
Et pour obtenir des fichiers sans extension spécifique: Cela produirait tous les fichiers qui n'ont pas d'extension spécifique dans votre répertoire actuel.
getFileWithoutExt(){
local extension="$1"
if (( $# == 1 )); then
for file in *; do
if [[ ! $file =~ \.$extension$ ]]; then
echo $file
fi
done
else
echo "Usage: ${FUNCNAME[0]} <extension>"
fi
}
De même pour obtenir des fichiers sans mp3
l'extension suffit simplement:
getFileWithoutExt mp3
Pour plus d'informations:
https://stackoverflow.com/questions/407184/how-to-check-the-extension-of-a-filename-in-a-bash-script
https://stackoverflow.com/questions/18278990/easiest-way-to-check-for-file-extension-in-bash/1828035