Как мне найти файлы, которые не заканчиваются переводом строки / перевода строки? - PullRequest
25 голосов
/ 08 января 2011

Как мне перечислить обычные текстовые (.txt) имена файлов, которые не заканчиваются символом новой строки?

например: список (вывод) этого имени файла:

$ cat a.txt
asdfasdlsad4randomcharsf
asdfasdfaasdf43randomcharssdf
$ 

и не указывать (выводить) это имя файла:

$ cat b.txt
asdfasdlsad4randomcharsf
asdfasdfaasdf43randomcharssdf

$

Ответы [ 11 ]

24 голосов
/ 19 декабря 2013

Используйте pcregrep, версию grep для Perl-совместимых регулярных выражений, которая поддерживает многострочный режим с использованием флага -M, который можно использовать для совпадения (или не совпадения), если в последней строке была новая строка:

pcregrep -LMr '\n$' .

В приведенном выше примере мы говорим о рекурсивном (-r) поиске файлов в текущем каталоге (.), которые не соответствуют (-L) нашему многострочному (-M) регулярному выражению, которое ищет новую строку вконец файла ('\n$')

При изменении -L на -l будут перечислены файлы, в которых do есть переводы строк.

pcregrepможет быть установлен на MacOS с пакетом homebrew pcre: brew install pcre

18 голосов
/ 05 сентября 2014

Хорошо, теперь моя очередь, я попробую:

find -type f -print0 | xargs -0 -L1 bash -c 'test "$(tail -c 1 "$0")" && echo "No new line at end of $0"'
8 голосов
/ 08 января 2011

Попробуйте:

find -type f -exec sh -c '[ -z "$(sed -n "\$p" "$1")" ]' _ {} \; -print

Он будет печатать имена файлов, которые заканчиваются пустой строкой. Для печати файлов, которые не заканчиваются пустой строкой, измените значение -z на -n.

3 голосов
/ 03 августа 2016

Если вы используете 'ack' (http://beyondgrep.com) в качестве альтернативы grep, вы просто запускаете это:

ack -v '\n$'

На самом деле он ищет все строки, которые не совпадают (-v) с новой строкой в ​​конце строки.

2 голосов
/ 31 июля 2017

Большинство решений на этой странице не работают для меня (FreeBSD 10.3 amd64).Решение Ian Will OSX работает почти всегда, но за ним довольно трудно следовать: - (

Существует простое решение, которое почти всегда работает тоже: (если $ f - это файл):

sed -i '' -e '$ a \' "$ f"

Существует серьезная проблема с решением sed: оно никогда не дает вам возможности просто проверить (и не добавлять новую строку).

Оба вышеупомянутых решения не работают для файлов DOS. Я думаю, что наиболее переносимое / пригодное для сценариев решение, возможно, самое простое, которое я разработал сам:объединяет файл / unix2dos / tail.В работе вам, вероятно, потребуется использовать «f» в кавычках и получить вывод хвоста (встроенный в переменную оболочки с именем last), так как \ «$ f \»

if file $f | grep 'ASCII text' > /dev/null; then
    if file $f | grep 'CRLF' > /dev/null; then
        type unix2dos > /dev/null || exit 1
        dos2unix $f
        last="`tail -c1 $f`"
        [ -n "$last" ] && echo >> $f
        unix2dos $f
    else
        last="`tail -c1 $f`"
        [ -n "$last" ] && echo >> $f
    fi
fi

Надеюсь, это кому-нибудь поможет.1014 *

2 голосов
/ 08 января 2011

Это должно сработать:

#!/bin/bash

for file in `find $1 -type f -name "*.txt"`;
do
        nlines=`tail -n 1 $file | grep '^$' | wc -l`
        if [ $nlines -eq 1 ]
                then echo $file
        fi
done;

Назовите это так: ./script dir

например. ./script /home/user/Documents/ -> перечисляет все текстовые файлы в /home/user/Documents, заканчивающиеся \n.

2 голосов
/ 08 января 2011

Это клудги;кто-то наверняка может сделать лучше:

for f in `find . -name '*.txt' -type f`; do
    if test `tail -c 1 "$f" | od -c | head -n 1 | tail -c 3` != \\n; then
        echo $f;
    fi
done

NB это ответ на вопрос в заголовке, который отличается от вопроса в теле (который ищет файлы, заканчивающиеся на \ n \ n, я думаю).

1 голос
/ 10 сентября 2015

Этот пример работает для меня на OSX (многие из вышеперечисленных решений этого не сделали)

for file in `find . -name "*.java"`
do
  result=`od -An -tc -j $(( $(ls -l $file  | awk '{print $5}') - 1 )) $file`
  last_char=`echo $result | sed 's/ *//'`
  if [ "$last_char" != "\n" ]
  then
    #echo "Last char is .$last_char."
    echo $file
  fi
done
1 голос
/ 08 января 2011

Поскольку у вашего вопроса есть тег perl, я выложу ответ, в котором он используется:

find . -type f -name '*.txt' -exec perl check.pl {} +

где check.pl следующий:

#!/bin/perl 

use strict;
use warnings;

foreach (@ARGV) {
    open(FILE, $_);

    seek(FILE, -2, 2);

    my $c;

    read(FILE,$c,1);
    if ( $c ne "\n" ) {
        print "$_\n";
    }
    close(FILE);
}

Этот Perl-скрипт просто открывает, по одному за раз, файлы, передаваемые как параметры, и читает только предпоследний символ; если это не символ новой строки, он просто печатает имя файла, иначе ничего не делает.

1 голос
/ 08 января 2011

Другой вариант:

$ find . -name "*.txt" -print0 | xargs -0I {} bash -c '[ -z "$(tail -n 1 {})" ] && echo {}'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...