Je sais que je peux trouver des fichiers en utilisant find
: find . -type f -name 'sunrise'
. Exemple de résultat:
./sunrise
./events/sunrise
./astronomy/sunrise
./schedule/sunrise
Je sais également que je peux déterminer le type de fichier d'un fichier: file sunrise
. Exemple de résultat:
sunrise: PEM RSA private key
Mais comment puis-je trouver des fichiers par type de fichier?
Par exemple, my-find . -type f -name 'sunrise' -filetype=bash-script
:
./astronomy/sunrise
./schedule/sunrise
"Types de fichiers" sur un système Unix sont des choses comme des fichiers normaux, des répertoires, des canaux nommés, des fichiers spéciaux de caractères, des liens symboliques, etc. Ce sont les types de fichiers sur lesquels find
peut filtrer avec son option -type
.
L'utilitaire find
ne peut pas à lui seul faire la distinction entre un "script Shell", un "fichier image JPEG" ou tout autre type de fichier normal . Ces types de données peuvent cependant être distingués par l'utilitaire file
, qui examine des signatures particulières dans les fichiers eux-mêmes pour déterminer leur type.
Une manière courante d'étiqueter les différents types de fichiers de données est par leur type MIME , et file
est capable de déterminer le type MIME d'un fichier.
Utilisation de file
avec find
pour détecter le type MIME de fichiers normaux, et utilisez-le uniquement pour rechercher des scripts Shell:
find . -type f -exec sh -c '
case $( file -bi "$1" ) in
*/x-shellscript*) exit 0
esac
exit 1' sh {} ';' -print
ou, en utilisant bash
,
find . -type f \
-exec bash -c '[[ "$( file -bi "$1" )" == */x-shellscript* ]]' bash {} ';' \
-print
Ajoutez -name sunrise
Avant le -exec
Si vous ne souhaitez détecter que les scripts portant ce nom.
La commande find
ci-dessus trouvera tous les fichiers normaux dans ou en dessous du répertoire courant, et pour chacun de ces fichiers, appelez un court script Shell en ligne. Ce script exécute file -bi
Sur le fichier trouvé et se termine avec un état de sortie nul si la sortie de cette commande contient la chaîne /x-shellscript
. Si la sortie ne contient pas cette chaîne, elle se termine avec un état de sortie différent de zéro, ce qui fait que find
continue immédiatement avec le fichier suivant. S'il s'avère que le fichier est un script Shell, la commande find
procédera à la sortie du chemin d'accès du fichier (le -print
À la fin, qui pourrait également être remplacé par une autre action).
La commande file -bi
Affichera le type MIME du fichier. Pour un script Shell sur Linux (et la plupart des autres systèmes), ce serait quelque chose comme
text/x-shellscript; charset=us-ascii
tandis que sur les systèmes avec une variante légèrement plus ancienne de l'utilitaire file
, il peut être
application/x-shellscript
Le bit commun est la sous-chaîne /x-shellscript
.
Notez que sur macOS, vous devez utiliser file -bI
Au lieu de file -bi
Pour des raisons (le -i
Fait quelque chose de très différent). La sortie sur macOS est similaire à celle d'un système Linux.
Souhaitez-vous effectuer une action personnalisée sur chaque script Shell trouvé, vous pouvez le faire avec un autre -exec
À la place de -print
Dans les commandes find
ci-dessus, mais cela être également possible de faire
find . -type f -exec sh -c '
for pathname do
case $( file -bi "$pathname" ) in
*/x-shellscript*) ;;
*) continue
esac
# some code here that acts on "$pathname"
done' sh {} +
ou, avec bash
,
find . -type f -exec bash -c '
for pathname do
[[ "$( file -bi "$pathname" )" != */x-shellscript* ]] && continue
# some code here that acts on "$pathname"
done' bash {} +
En relation:
Vous pouvez exécuter find
sur chaque fichier trouvé, puis rechercher le résultat qui vous intéresse.
# When looking for ASCII Text
find . -type -exec file {} \; | grep "ASCII"
# or for MS Word Documents
find . -type f -exec file {} \; | grep "Microsoft Word"
Je suggère de rendre le modèle de recherche aussi proche que possible de vos attentes afin de maintenir le nombre de fausses correspondances faibles.
Attention, les fichiers avec des sauts de ligne dans leurs noms de fichiers peuvent provoquer des problèmes avec cette approche.
Utilisation de Perl
File::LibMagic
module:
Perl -MFile::LibMagic=:easy -MFile::Find -le '
find sub {
print $File::Find::name if
$_ eq "sunrise" and
-f and
MagicFile$_ eq "PEM RSA private key"
}, @ARGV' -- .