Est-il possible d'utiliser la find
commande pour rechercher tous les fichiers "non-binaires" dans un répertoire? Voici le problème que j'essaie de résoudre.
J'ai reçu une archive de fichiers d'un utilisateur Windows. Cette archive contient le code source et les fichiers image. Notre système de construction ne fonctionne pas bien avec les fichiers avec des fins de lignes Windows. J'ai un programme en ligne de commande ( flip -u
) qui basculera les fins de ligne entre * nix et windows. Donc, j'aimerais faire quelque chose comme ça
find . -type f | xargs flip -u
Toutefois, si cette commande est exécutée sur un fichier image ou un autre fichier multimédia binaire, le fichier sera corrompu. Je me rends compte que je pourrais construire une liste d'extensions de fichiers et filtrer avec cela, mais je préférerais que quelque chose ne dépende pas de moi pour maintenir cette liste à jour.
Alors, est-il possible de trouver tous les fichiers non binaires dans une arborescence de répertoires? Ou y a-t-il une solution alternative que je devrais envisager?
file
utilitaire quelque part dans votre script / pipeline pour déterminer s'il s'agit d'un fichier de données ou de texteRéponses:
J'utiliserais
file
et acheminerais la sortie dans grep ou awk pour trouver des fichiers texte, puis j'extraireais seulement la partie nomfichier defile
la sortie de et acheminerais cela dans xargs.quelque chose comme:
Notez que le grep recherche le 'texte ASCII' plutôt que n'importe quel 'texte' - vous ne voudrez probablement pas vous mêler des documents Rich Text, des fichiers texte Unicode, etc.
Vous pouvez également utiliser
find
(ou autre chose) pour générer une liste de fichiers à examiner avecfile
:L'
-d'\n'
argument de xargs fait en sorte que xargs traite chaque ligne d'entrée comme un argument séparé, ce qui permet de gérer les noms de fichiers avec des espaces et d'autres caractères problématiques. c'est-à-dire que c'est une alternative au casxargs -0
où la source d'entrée ne génère pas ou ne peut pas générer de sortie séparée par NULL (telle quefind
l'-print0
option de). Selon le journal des modifications, xargs a obtenu l' option-d
/--delimiter
en septembre 2005, donc il devrait figurer dans toute distribution non-ancienne de Linux (je n'étais pas sûr, c'est pourquoi j'ai vérifié - je me souvenais vaguement qu'il s'agissait d'un ajout "récent").Notez qu'un saut de ligne est un caractère valide dans les noms de fichiers, il sera donc cassé si un nom de fichier contient un saut de ligne. Pour les utilisateurs Unix typiques, ceci est pathologiquement insensé, mais n’est pas inconnu si les fichiers proviennent d’ordinateurs Mac ou Windows.
Notez également que ce
file
n'est pas parfait. Il est très efficace pour détecter le type de données dans un fichier mais peut parfois être confus.J'ai utilisé de nombreuses variantes de cette méthode plusieurs fois dans le passé avec succès.
la source
file
afficheEnglish text
plutôt queASCII text
sur mon système Solaris, donc je modifié cette partie en conséquence. Aussi, j'ai remplacéawk -F: '{print $1}'
par l'équivalentcut -f1 -d:
.grep -I
filtres binairestext
devrait suffire. Cela permettra également de prendre desfile
descriptions commeASCII Java program text
ouHTML document text
outroff or preprocessor input text
.ASCII text
éviter de gâcher les RTF.Non, un fichier binaire ou non-binaire n'a rien de spécial. Vous pouvez utiliser des méthodes heuristiques telles que 'ne contient que des caractères dans 0x01–0x7F', mais cela appellera des fichiers texte contenant des fichiers binaires contenant des caractères non ASCII et des fichiers binaires malchanceux.
Maintenant, une fois que vous avez ignoré cela ...
fichiers zip
S'il provient de votre utilisateur Windows sous forme de fichier zip, le format zip prend en charge le marquage des fichiers en tant que fichiers binaires ou texte dans l'archive elle-même. Vous pouvez utiliser l'
-a
option de décompression pour y faire attention et convertir. Bien sûr, voyez le premier paragraphe pour savoir pourquoi cela n’est peut-être pas une bonne idée (le programme zip a peut-être mal compris lorsqu’il a créé l’archive).zipinfo vous indiquera quels fichiers sont binaires (b) ou textuels (t) dans sa liste de fichiers zip.
autres fichiers
La commande de fichier examinera un fichier et tentera de l'identifier. En particulier, vous trouverez probablement son
-i
option (type de sortie MIME) utile; convertir uniquement les fichiers de type text / *la source
Une solution générale pour traiter uniquement les fichiers non-binaires en
bash
utilisantfile -b --mime-encoding
:J'ai contacté l'auteur de l' utilitaire de fichiers et il a ajouté un
-00
paramètre astucieux dans la version 5.26 (publiée le 2016-04-16, par exemple dans Arch et Ubuntu 16.10 actuels) qui imprimefile\0result\0
plusieurs fichiers en même temps, ce qui vous permet de le faire par exemple:(La
awk
partie consiste à filtrer tous les fichiers non binaires.ORS
Constitue le séparateur de sortie.)Peut aussi être utilisé en boucle bien sûr:
Sur la base de ceci et de la précédente, j'ai créé un petit
bash
script pour filtrer les fichiers binaires qui utilise la nouvelle méthode en utilisant le-00
paramètre defile
dans les versions les plus récentes et qui revient à la méthode précédente sur les versions antérieures:Ou ici, un plus POSIX-y, mais il nécessite un support pour
sort -V
:la source
La réponse acceptée ne les a pas toutes trouvées pour moi. Voici un exemple d'utilisation de grep
-I
pour ignorer les fichiers binaires et ignorer tous les fichiers cachés ...Ici, il est utilisé dans une application pratique: dos2unix
https://unix.stackexchange.com/a/365679/112190
la source
La réponse de Cas est bonne, mais elle suppose des noms de fichiers sains ; en particulier, on suppose que les noms de fichiers ne contiendront pas de nouvelles lignes.
Il n’ya pas de bonne raison de faire cette hypothèse ici, car il est assez simple (et en fait plus propre à mon avis) de traiter cette affaire correctement aussi:
La
find
commande utilise uniquement les fonctionnalités spécifiées par POSIX . Utiliser-exec
des commandes arbitraires en tant que tests booléens est simple, robuste (gère correctement les noms de fichiers impairs) et plus portable que-print0
.En fait, toutes les parties de la commande sont spécifiées par POSIX à l'exception de
flip
.Notez que
file
cela ne garantit pas l'exactitude des résultats renvoyés. Cependant, en pratique, l’obtention de "texte ASCII" dans la sortie est assez fiable.(Il pourrait manquer certains fichiers texte peut - être, mais il est très peu probable d'identifier correctement un fichier binaire comme « texte ASCII » et mutiler it-nous donc pécher par excès de prudence.)
la source
calls
peut être assez lent, par exemple pour les vidéos, il vous expliquera tout sur l'encodage.-
.file
, cela peut prendre plusieurs fichiers comme arguments.find
commande préfixera./
tout nom de fichier transmis à la commande shell; (3) Utilisergrep
un test sur unefile
sortie de commande unique à la fois est la seule façon POSIX que je puisse voir pour garantir un traitement correct des noms de fichiers pouvant contenir des nouvelles lignes.file
prend en charge le--mime-encoding
drapeau et le--
séparateur, qui ne sont aucunement garantis par POSIX .Ceci trouvera tous les fichiers normaux (
-type f
) dans le répertoire courant (ou en dessous) quigrep
pense être non vides et non binaires.Il utilise
grep -I
pour distinguer les fichiers binaires et non binaires. L'-I
indicateur et entraîneragrep
à quitter avec un statut de sortie différent de zéro lorsqu'il détectera qu'un fichier est binaire. Selon le casgrep
, un fichier "binaire" est un fichier contenant des caractères en dehors de la plage imprimable ASCII.L'
-q
option to legrep
fera quitter avec un statut de sortie nul si le modèle donné est trouvé, sans émettre de données. Le motif que nous utilisons est un seul point, qui correspond à n’importe quel caractère.S'il s'avère que le fichier est non binaire et qu'il contient au moins un caractère, le nom du fichier est imprimé.
Si vous vous sentez courageux, vous pouvez également vous y connecter
flip -u
:la source
Essaye ça :
Où l'argument de
grep '[^ -~]'
est'[^<tab><space>-~]'
.Si vous le tapez sur une ligne de commande shell, tapez Ctrl+ Vavant Tab. Dans un éditeur, il ne devrait y avoir aucun problème.
'[^<tab><space>-~]'
correspond à tout caractère qui n'est pas du texte ASCII (les retours à la ligne sont ignorés pargrep
).-L
imprimera uniquement le nom de fichier des fichiers qui ne correspondent pas-Z
affichera les noms de fichiers séparés par un caractère nul (pourxargs -0
)la source
grep -P
(si disponible)\t
est disponible avec Perl . Vous pouvez également utiliser la traduction des paramètres régionaux si le shell le prend en charge:$'\t'
(bash
etzsh
faire).Solution alternative:
La commande dos2unix convertit les fins de ligne de Windows CRLF en Unix LF et ignore automatiquement les fichiers binaires. Je l'applique de manière récursive en utilisant:
la source
dos2unix
peut prendre plusieurs noms de fichiers comme argument, il est beaucoup plus efficace de le fairefind . -type f -exec dos2unix {} +
sudo find / (-type f -and -path '* / git / *' -iname 'README') -exec grep -liI '100644 \ | 100755' {} \; -exec bascule -u {} \;
i. (-type f -and -path '* / git / *' -iname 'README'): recherche les fichiers dans un chemin contenant le nom git et le fichier portant le nom README. Si vous connaissez un dossier spécifique et un nom de fichier à rechercher, il sera utile.
La commande ii.-exec exécute une commande sur le nom du fichier généré par find
iii. \; indique la fin de la commande
iv. {} est la sortie du fichier / nom de dossier trouvé lors de la recherche précédente.
Les commandes v.Multiple peuvent être exécutées ultérieurement. En ajoutant -exec "commande" \; comme avec -exec flip -u \;
vii.grep
vous pouvez cloner ce répertoire de test et l'essayer: https://github.com/alphaCTzo7G/stackexchange/tree/master/linux/findSolution204092017
réponse plus détaillée ici: https://github.com/alphaCTzo7G/stackexchange/blob/master/linux/findSolution204092017/README.md
la source