11

I have a list of files.txt, below:

-rw-rw-r-- 1 root dev 11 May 16 12:18 20_SumActive.txt  
-rw-rw-r-- 1 root dev 11 May 16 12:18 22_SumActive.txt  
-rw-rw-r-- 1 root dev  7 May 16 12:18 24_SumActive.txt  
-rw-rw-r-- 1 root dev  0 May 16 12:18 26_SumActive.txt  
-rw-rw-r-- 1 root dev  0 May 16 12:18 28_SumActive.txt  

Output:

kpgmeddev01> cat 2[0-8]_SumActive.txt   
Sum: 47760  
Sum: 72000  
Sum: 0

How to get output as below:

Sum: 47760  
Sum: 72000  
Sum: 0  
[Blank]  
[Blank]  

Need guidance.

4
  • Do the files ever contain more then one line,?
    – roaima
    May 16, 2018 at 5:25
  • No, only 1 line
    – Fewong
    May 16, 2018 at 6:37
  • 1
    Uh, when you wrote [Blank] did you mean those 7 characters or did you intend to indicate an empty line?
    – roaima
    May 17, 2018 at 7:41
  • 1
    By not using cat. Don't constrain your self. May 17, 2018 at 21:42

8 Answers 8

20

cat cannot output data that does not exist in the files. If a file is empty, it does not even have a newline character to provide an empty line as output.

You could make sure that the files contained at least a single newline character.

This is how you use GNU awk to ensure that (this modifies the empty files):

awk 'ENDFILE { if (FNR == 0) printf("\n") >>FILENAME }' 2[0-8]_SumActive.txt   

The ENDFILE block will be executed after finishing reading any of the files. If FNR is zero, we never saw any lines in the file, so we insert a single newline into it. The script then continues with the next file.

You can then use cat as you did in the question.


Alternatively, without changing the files, using GNU awk instead of cat:

awk 'ENDFILE { if (FNR == 0) printf("\n") } 1' 2[0-8]_SumActive.txt

This does the same kind of detection of empty files as above, but prints the newline to standard output rather than to the file. The 1 at the end could be replaced by { print } and will cause all data in the non-empty files to be outputted.


Alternatively, a shell loop (should work in any POSIX shell):

for name in ./2[0-8]_SumActive.txt; do
    if [ -s "$name" ]; then
        cat "$name"
    else
        printf '\n'
    fi
done

The -s test will be true if the file exists and has a size greater than zero.


If you want the literal string [Blank] to be outputted for empty files, simply insert that string in front of \n in the calls to printf above (this will also work in the awk code).

4
  • 2
    @Fewong Good! If this solves your issue, please consider accepting the answer.
    – Kusalananda
    May 16, 2018 at 9:13
  • @Fewong: Or accept another answer that helps you even better - it's good practice to give every timezone a chance, so there's no hurry.
    – MSalters
    May 16, 2018 at 14:29
  • @Fewong Definitely no hurry. Stephané has written a short and compact solution too, which looks promising.
    – Kusalananda
    May 16, 2018 at 14:38
  • @Kusalananda, thanks and I tested it worked.
    – Fewong
    Jun 7, 2018 at 10:23
16

With perl

perl -0777 -pe 's/\n?\z/\n/' 2[0-8]_SumActive.txt

Which adds a newline character if missing at the end, so would output an empty line for empty files, but would also add a newline for non-empty files that miss ones (and would end up being concatenated on a single line with cat).

1
  • nice suggestion
    – erTugRul
    May 16, 2018 at 11:22
13

(This is not exactly what you ask, but:) In this type of situations I prefer to use head

$ head -z 2[0-8]_SumActive.txt
==> 21_SumActive.txt <==
Sum: 47760  
Sum: 72000  
Sum: 0  

==> 22_SumActive.txt <==

==> 25_SumActive.txt <==

==> 28_SumActive.txt <==

Normally this is what you want. If not it is easy to sed it later

12

With xargs and grep you could try something like:

$>ls | xargs -n1 sh -c 'grep "" $0 || echo "[Blank]"'
Sum: 47760
Sum: 72000
Sum: 0
[Blank]
[Blank]
2
  • 4
    Perhaps not the fastest solution (forking a shell for each file), but only one so far which will actually work if you have millions of such files in current directory (not using shell expansions and hitting ARGV limit). May 17, 2018 at 14:41
  • 1
    @MatijaNalis: Very true! But you really wouldn't care for 5 files.
    – FloHimself
    May 18, 2018 at 5:30
6

Assuming that by [Blank] you mean literal blank lines, this should work:

paste -s 2[0-8]_SumActive.txt
6

You can test each file to see if it's zero length before attempting to display its contents:

for f in 2[0-8]_SumActive.txt;
do
    [[ -s "$f" ]] && awk 1 "$f" || echo '[Blank]'
done

I've used awk 1 "$f" instead of cat "$f" because awk guarantees to end the output of a file with a newline.

In your question, if you intended that [blank] should not be a literal, but just a blank line, you can implement this using the code above and removing '[Blank]' from the end of the echo statement.

5

I am assuming your files 26_SumActive.txt and 28_SumActive.txt are empty and you need blank lines when displaying their contents

For this , you can just iterate through your list of files, and cat their contents, and if file is empty, echo blank line.

[ -s FILE ] True if FILE exists and has a size greater than zero.

$ for i in $(ls 2[0-8]_SumActive.txt) ; do  cat $i;  if [ ! -s $i ]; then echo -e ""; fi; done
Sum: 47760  
Sum: 72000  
Sum: 0  
[ Blank Line]
[ Blank Line ]
2
  • 1
    Or if [ -s $i ]; then cat $i; else echo -e ""; fi;. Still +1 for a simple test using just standard shell functionality.
    – MSalters
    May 16, 2018 at 14:32
  • 2
    Or just cat "$i"; test -s "$i" || echo - no need for that unwieldy if or non-portable echo flags. May 17, 2018 at 10:35
1
cat 2[0-8]_SumActive.txt -

where - will enable cat to read from standard input.

So, after displaying the content of your files cat will wait for your input. You can make your desired input, by hitting enter for literal blanks or [Blank] if its what you want. After each input hit enter, once all input are made press ^D (Ctrl+D) and you are done.

P.S: For each input you will get respective output.

cat 2[0-8]_SumActive.txt - 4[0-8]_SumActive.txt

With this you able to put blanks or something else you want, between two sequence ofoutputs.

1
  • On this basis you might as well just offer cat as a solution and allow the OP to your what they want.
    – roaima
    May 17, 2018 at 22:59

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .