How do I find files that do not end with a newline/linefeed?

后端 未结 12 1247
广开言路
广开言路 2021-02-01 03:45

How can I list normal text (.txt) filenames, that don\'t end with a newline?

e.g.: list (output) this filename:

$ cat a.txt
asdfasdlsad4rand         


        
相关标签:
12条回答
  • 2021-02-01 04:15

    This should do the trick:

    #!/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;
    

    Call it this way: ./script dir

    E.g. ./script /home/user/Documents/ -> lists all text files in /home/user/Documents ending with \n.

    0 讨论(0)
  • 2021-02-01 04:15

    Most solutions on this page do not work for me (FreeBSD 10.3 amd64). Ian Will's OSX solution does almost-always work, but is pretty difficult to follow : - (

    There is an easy solution that almost-always works too : (if $f is the file) :

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

    There is a major problem with the sed solution : it never gives you the opportunity to just check (and not append a newline).

    Both the above solutions fail for DOS files. I think the most portable/scriptable solution is probably the easiest one, which I developed myself : - )

    Here is that elementary sh script which combines file/unix2dos/tail. In production, you will likely need to use "$f" in quotes and fetch tail output (embedded into the shell variable named last) as \"$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
    

    Hope this helps someone.

    0 讨论(0)
  • 2021-02-01 04:16

    This is kludgy; someone surely can do better:

    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
    

    N.B. this answers the question in the title, which is different from the question in the body (which is looking for files that end with \n\n I think).

    0 讨论(0)
  • 2021-02-01 04:16

    This example works for me on OSX (many of the above solutions did not)

    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
    
    0 讨论(0)
  • 2021-02-01 04:23

    The best oneliner I could come up with is this:

    git grep --cached -Il '' | xargs -L1 bash -c 'if test "$(tail -c 1 "$0")"; then echo "No new line at end of $0"; exit 1; fi'
    

    This uses git grep, because in my use-case I want to ensure files commited to a git branch have ending newlines.

    If this is required outside of a git repo, you can of course just use grep instead.

    grep -RIl '' . | xargs -L1 bash -c 'if test "$(tail -c 1 "$0")"; then echo "No new line at end of $0"; exit 1; fi'
    

    Why I use grep? Because you can easily filter out binary files with -I.

    Then the usual xargs/tail thingy found in other answers, with the addition to exit with 1 if a file has no newline. So this can be used in a pre-commit githook or CI.

    0 讨论(0)
  • 2021-02-01 04:23

    Another option:

    $ find . -name "*.txt" -print0 | xargs -0I {} bash -c '[ -z "$(tail -n 1 {})" ] && echo {}'
    
    0 讨论(0)
提交回复
热议问题