J'ai des fichiers dans les sous-répertoires du répertoire courant qui peuvent ou non avoir de nouvelles lignes à la fin; comment puis-je trouver des fichiers qui n'ont pas de nouvelle ligne à la fin?
J'ai essayé ça:
find . -name '*.styl' | while read file; do
awk 'END{print}' $file | grep -E '^$' > /dev/null || echo $file;
done
mais ça ne marche pas. awk 'END{print}' $file
imprime la ligne avant une nouvelle ligne vide, identique à tail -n 1 $file
.
awk 'END{print}' $file
: ceci ignore totalement le contenu de $ file, et après avoir terminé l'analyse de tous les fichiers contenus dans "$ file", il ajoute une nouvelle ligne. Comme c'est la seule chose que la commande awk imprime, elle pourrait être remplacée par:printf '\n'
(sans aucun mentino de $ file) et faire la même chose. Je pense que ce n'est PAS ce que vous visiez (c'est-à-dire: imprimer la dernière ligne du fichier?)c
et FreeBSD aussi, mais je n'avais pas remarqué qu'il était documenté comme dépendant de l'implémentation: gnu.org/software/gawk/manual/… . Donc , il ne se produit mais pas toujours.Réponses:
Pour clarifier, le caractère LF (aka
\n
ou newline) est le délimiteur de ligne , ce n'est pas le séparateur de ligne. Une ligne n'est terminée que si elle se termine par un caractère de nouvelle ligne. Un fichier qui contient uniquementa\nb
n'est pas un fichier texte valide car il contient des caractères après la dernière ligne. Idem pour un fichier qui ne contient quea
. Un fichier qui contienta\n
contient une ligne non vide.Ainsi, un fichier qui se termine par au moins une ligne vide se termine par deux caractères de nouvelle ligne ou contient un seul caractère de nouvelle ligne.
Si:
Sorties
\n
ou\n \n
, alors le fichier contient au moins une ligne vide de fin. S'il ne sort rien, alors c'est un fichier vide, s'il sort<anything-but-\0> \n
, alors il se termine par une ligne non vide. Rien d'autre, ce n'est pas un fichier texte.Maintenant, pour utiliser cela pour trouver des fichiers qui se terminent par une ligne vide, OK c'est efficace (en particulier pour les fichiers volumineux) en ce sens qu'il ne lit que les deux derniers octets des fichiers, mais d'abord la sortie n'est pas facilement analysable par programme, d'autant plus que c'est pas cohérente d'une implémentation
od
à l'autre, et nous aurions besoin d'en exécutertail
uneod
par fichier.(pour trouver les fichiers se terminant par une ligne vide) exécuterait le moins de commandes possible mais signifierait lire le contenu complet de tous les fichiers.
Idéalement, vous auriez besoin d'un shell capable de lire lui-même la fin d'un fichier.
Avec
zsh
:la source
are_textfiles () { nontext=0; rem="return 0 if all args are files with terminating newline, or n [=number of non-textfiles]" ; for f in "$@" ; do [ -f "$f" ] && { tail -c 1 "$f" | od -An -vtc | grep "\\n" ;} >/dev/null 2>&1 || ((nontext++)) ; done ; return $nontext ; }
. Utiliser comme:if ( are_textfiles this that otherthing ) ; then echo all are text files ; else echo "are_textfiles returned : $?" ; fi
Avec
gnu sed
et un shell commezsh
(oubash
avecshopt -s globstar
):cela vérifie si la dernière ligne de chaque fichier n'est pas vide, si c'est le cas, elle imprime le nom du fichier.
Si vous voulez l'inverse (imprimer les noms de fichiers si la dernière ligne est vide) remplacez simplement
/./
par/^$/
la source
-s
en action auparavant. Merci GNU!Un fichier texte correctement terminé avec une dernière ligne vide se termine par deux
\n
.Ensuite, nous nous attendons à ce que ce
tail -c2
soit égal à$'\n\n'
.Malheureusement, les extensions de commande suppriment les nouvelles lignes à la fin. Nous aurons besoin d'un peu de peaufinage.
Nous pourrions même développer un peu pour vérifier quels fichiers n'ont pas de nouvelle ligne de fin:
Notez que la nouvelle ligne pourrait être changée en quelque chose comme
$'\r\n
si nécessaire.Dans ce cas, changez également
tail -c2
entail -c4
.la source
la source
cat $file 2>&1 /dev/null
, ou si cela est Bash seule,cat $file &> /dev/null
.$file
partout où il est utilisé - et s'il vous plaît, utilisez$(commands ...)
au lieu de`backticks`
...