Problem with Bash output redirection

前端 未结 11 1879
梦毁少年i
梦毁少年i 2020-12-06 06:19

I was trying to remove all the lines of a file except the last line but the following command did not work, although file.txt is not empty.

$cat file.txt |ta         


        
相关标签:
11条回答
  • 2020-12-06 07:15

    As Lewis Baumstark says, it doesn't like it that you're writing to the same filename.

    This is because the shell opens up "file.txt" and truncates it to do the redirection before "cat file.txt" is run. So, you have to

    tail -1 file.txt > file2.txt; mv file2.txt file.txt
    
    0 讨论(0)
  • It seems to not like the fact you're writing it back to the same filename. If you do the following it works:

    $cat file.txt | tail -1 > anotherfile.txt
    
    0 讨论(0)
  • 2020-12-06 07:18

    tail -1 > file.txt will overwrite your file, causing cat to read an empty file because the re-write will happen before any of the commands in your pipeline are executed.

    0 讨论(0)
  • 2020-12-06 07:19

    Redirecting from a file through a pipeline back to the same file is unsafe; if file.txt is overwritten by the shell when setting up the last stage of the pipeline before tail starts reading off the first stage, you end up with empty output.

    Do the following instead:

    tail -1 file.txt >file.txt.new && mv file.txt.new file.txt
    

    ...well, actually, don't do that in production code; particularly if you're in a security-sensitive environment and running as root, the following is more appropriate:

    tempfile="$(mktemp file.txt.XXXXXX)"
    chown --reference=file.txt -- "$tempfile"
    chmod --reference=file.txt -- "$tempfile"
    tail -1 file.txt >"$tempfile" && mv -- "$tempfile" file.txt
    

    Another approach (avoiding temporary files, unless <<< implicitly creates them on your platform) is the following:

    lastline="$(tail -1 file.txt)"; cat >file.txt <<<"$lastline"
    

    (The above implementation is bash-specific, but works in cases where echo does not -- such as when the last line contains "--version", for instance).

    Finally, one can use sponge from moreutils:

    tail -1 file.txt | sponge file.txt
    
    0 讨论(0)
  • 2020-12-06 07:20
    echo "$(tail -1 file.txt)" > file.txt
    
    0 讨论(0)
提交回复
热议问题