que je devais faire ce récursive, et voici ce que je suis venu avec:
find -type f | while read l; do iconv -s -f utf-16le -t utf-8 "$l" | nl -s "$l: " | cut -c7- | grep 'somestring'; done
Ceci est absolument horrible et très lent; Je suis certain qu'il ya une meilleure façon et j'espère que quelqu'un peut l'améliorer - mais j'étais pressé: P
Ce que les pièces font:
find -type f
donne une liste récursive des noms de fichiers avec des chemins par rapport au courant
while read l; do ... done
Boucle de boucle; pour chaque ligne de la liste des chemins de fichier, placez le chemin dans $l
et faites le chose dans la boucle. (Pourquoi ai-je utilisé une boucle shell à la place de xargs, ce qui aurait été beaucoup plus rapide: j'ai besoin de préfixer chaque ligne de la sortie avec le nom du fichier en cours ... Impossible de penser à un moyen de le faire si je nourrissais plusieurs fichiers à la fois à iconv, et que je vais être faire un fichier à la fois de toute façon, la boucle shell est plus facile syntaxe/échappement)
iconv -s -f utf-16le -t utf-8 "$l"
Convertir le fichier nommé dans $l
:. suppose que le fichier d'entrée est utf-16 petit-boutiste et le convertit en utf-8. Le -s
fait iconv se taire sur toutes les erreurs de conversion (il y aura beaucoup, car certains fichiers dans cette structure de répertoires ne sont pas utf-16). La sortie de cette conversion va à stdout.
nl -s "$l: " | cut -c7-
C'est un hack: nl
inserts de numéros de ligne, mais il arrive d'avoir un « utiliser cette chaîne arbitraire pour séparer le numéro de la ligne » paramètre, donc je mis le nom du fichier (suivi par deux points et de l'espace) dans cela. Ensuite, j'utilise cut
pour supprimer le numéro de ligne, en ne laissant que le préfixe du nom de fichier. (Pourquoi je n'ai pas utilisé sed
: s'échapper est beaucoup plus facile de cette façon.Si j'ai utilisé une expression sed, je dois m'inquiéter des caractères d'expression régulière dans les noms de fichiers, qui dans mon cas il y avait beaucoup de nl
est beaucoup plus bête et prendra simplement le paramètre -s
entièrement et le shell gère l'échappement pour moi.)
Donc, à la fin de ce pipeline, j'ai converti un tas de fichiers en lignes d'utf-8 , préfixé avec le nom de fichier, que je grep ensuite. S'il y a des correspondances, je peux dire dans quel fichier elles se trouvent depuis le préfixe.
Avertissements
- Cela est beaucoup, beaucoup plus lent que
grep -R
, parce que je fraye une nouvelle copie de iconv
, nl
, cut
et grep
pour chaque fichier. C'est horrible.Tout ce qui n'est pas utf-16le entrera comme une poubelle complète, donc s'il y a un fichier ASCII normal qui contient 'somestring', cette commande ne le signalera pas - vous devez aussi faire un grep -R
normal comme cette commande (et si vous avez plusieurs types de codage Unicode, comme certains fichiers big-endian et certains little-endian, vous devez ajuster cette commande et l'exécuter à nouveau pour chaque encodage différent).
- Les fichiers dont le nom contient 'somestring' apparaîtront dans la sortie, même si leur contenu ne correspond pas.
... ce n'est pas ASCII si les caractères ont une longueur de deux octets. –
Je veux dire la plage de caractères ASCII (U + 0000 à U + 007F), pas le codage ASCII. – taw