Je dois exécuter périodiquement une commande qui garantit que certains fichiers texte sont conservés en mode Linux. Malheureusement, dos2unix
modifie toujours le fichier, ce qui perturberait les horodatages des fichiers et des dossiers et provoquerait des écritures inutiles.
Le script que j'écris est en Bash, je préférerais donc des réponses basées sur Bash.
bash
text-processing
newlines
Adam Ryczkowski
la source
la source
test
parmyfile.txt
deux fois dans votre exemple pour éviter toute confusion avec/usr/bin/test
.-s
drapeau pour voir le résultat. Des pages de manuel:-s, --quiet, --silent suppress all normal output
Si l’objectif est simplement d’éviter d’affecter l’horodatage,
dos2unix
une option-k
ou--keepdate
permet de conserver l’horodatage. Il faudra toujours une écriture pour créer le fichier temporaire et le renommer, mais votre horodatage ne sera pas affecté.Si une modification du fichier est inacceptable, vous pouvez utiliser la solution suivante à partir de cette réponse .
la source
find ... -exec file ... | grep CRLF
pour un fichier avec des fins de ligne DOS (octets 0D 0A) "vous obtiendrez quelque chose comme:./1/dos1.txt: ASCII text, with CRLF line terminators
Comme vous pouvez le voir, cela contient la chaîne réelle CRLF et est donc comparé engrep
recherchant la chaîne simple CRLFVous pouvez essayer
grep
pour le code CRLF, octal:ou hex:
la source
grep
usage, car il me permet de répertorier facilement tous ces fichiers dans le répertoiregrep -lU $'\x0D' *
et de transmettre le résultatxargs
.Depuis la version
7.1
dos2unix a une-i
,--info
option pour obtenir des informations sur les sauts de ligne. Vous pouvez utiliser dos2unix lui-même pour tester les fichiers nécessitant une conversion.Exemple:
la source
Première méthode (
grep
):Comptez les lignes qui contiennent un retour chariot:
Comptez les lignes qui se terminent par un retour chariot:
Ceux-ci seront généralement équivalents; un retour de chariot à l'intérieur d'une ligne (c'est-à-dire pas à la fin) est rare.
Plus efficace:
C'est plus efficace
grep -c
doit lire tout le fichier, compter toutes les occurrences du motif, tout engrep -q
pouvant sortir dès la première apparition du motif.Remarques:
-U
option (c’est-à-dire utiliser-cU
ou-qU
), car GNUgrep
devine si le fichier est un fichier texte. S'il pense que le fichier est du texte, il ignore les retours à la ligne à la fin des lignes, pour que$
les expressions régulières fonctionnent "correctement" - même si l'expression régulière l'est\r$
! La spécification-U
(ou--binary
) annule cette approximation, cegrep
qui entraîne le traitement du ou des fichiers comme étant binaire et la transmission complète des données au mécanisme de correspondance, avec les terminaisons CR intactes.grep … $'\r\n' myfile.txt
, cargrep
traite\n
comme un délimiteur de motif. Tout commegrep -E 'foo|'
recherche des lignes contenantfoo
ou une chaîne NULL,grep $'\r\n'
recherche des lignes contenant\r
ou une chaîne NULL, et chaque ligne correspond à une chaîne NULL.Deuxième méthode (
file
):parce que
file
rapporte quelque chose comme:Variante plus sûre:
où
file -b
affiche uniquement le type de fichier et non le nom du fichier. Sans cela, un fichier dont le nomCRLF
inclurait les caractères déclencherait un faux positif.file - < filename
fonctionne même sifilename
commence par-
. Voir Script Bash: vérifiez si un fichier est un fichier texte .Notez que la vérification de la sortie
file
peut ne pas fonctionner dans un environnement local non anglais.la source
"$(echo -e '\r')"
par le beaucoup plus simple$'\r'
, bien que personnellement, je$'\r\n'
réduirais le nombre de faux positifs.grep $'\r\n'
semble correspondre à tous les fichiers de mon système ...grep -U $'\r$'
à empêcher d'grep
essayer de deviner les fins de ligne.-q
simplement définir le code de retour si une correspondance est trouvée,-c
ce qui nécessite une vérification supplémentaire. Personnellement, j’aime bien votre deuxième solution, bien qu’elle dépende beaucoup des caprices defile
et puisse ne pas fonctionner dans un environnement local autre que l’anglais.Utilisation
cat -A
Si ce fichier était créé sur des systèmes * NIX, il afficherait
Mais si ce fichier était créé sous Windows, il afficherait
^M
représenteCR
et$
représenteLF
. Notez que Windows n’a pas enregistré la dernière ligne avecCRLF
Cela ne change pas non plus le contenu du fichier.
la source
-A
pour chat. Un conseil cependant serait d'utilisercat -A file | less
si le fichier est trop gros. Je suis sûr qu'il n'est pas rare de devoir vérifier la fin d'un fichier pour un fichier particulièrement long. (Appuyezq
pour quitter moins)une fonction bash pour vous:
Ensuite, vous pouvez faire des choses comme
la source
isDosFile()
dans votre exemple:streamFile() { sed 's/\r$//' "$1" ; }
.Si un fichier comporte des fins de ligne CR-LF de style DOS / Windows, il affiche des caractères CR ("\ r") à la fin de chaque ligne, à l'aide d'un outil basé sur Unix.
Cette commande:
imprimera
filename
si le fichier contient une ou plusieurs lignes avec des fins de ligne de style Windows et n’imprimera rien s’il ne l’est pas. Sauf que le^M
doit être un caractère de retour chariot littéral, généralement entré dans le terminal en tapant Ctrl+ Vsuivi de Enter (ou Ctrl+ Vpuis Ctrl+ + M). Le shell bash vous permet d’écrire un retour chariot littéral comme$'\r'
( documenté ici ), vous pouvez donc écrire:D'autres coquilles peuvent fournir une fonctionnalité similaire.
Vous pouvez utiliser un autre outil à la place:
Cela se terminera avec le statut
1
(paramétrant$?
sur1
) si le fichier contient des fins de ligne de style Windows et avec le statut0
s'il ne le contient pas, ce qui le rend utile dans uneif
instruction shell (notez le manque de[
crochets]
):Un fichier peut contenir un mélange de fins de ligne de style Unix et Windows. Je suppose ici que vous voulez détecter les fichiers qui ont des fins de ligne de type Windows.
la source
$'\r'
, comme indiqué dans d'autres réponses à cette question.Utiliser
file
:la source
J'ai utilisé
qui semble fonctionner. Je trouve la sortie un peu plus facile à lire que
C'est également utile si vous ne pouvez pas installer
dos2unix
pour une raison quelconque.la source