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.

  • Do the files ever contain more then one line,? – roaima May 16 '18 at 5:25
  • No, only 1 line – Fewong May 16 '18 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 '18 at 7:41
  • 1
    By not using cat. Don't constrain your self. – ctrl-alt-delor May 17 '18 at 21:42
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).

|improve this answer|||||
  • 2
    @Fewong Good! If this solves your issue, please consider accepting the answer. – Kusalananda May 16 '18 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 '18 at 14:29
  • @Fewong Definitely no hurry. Stephané has written a short and compact solution too, which looks promising. – Kusalananda May 16 '18 at 14:38
  • @Kusalananda, thanks and I tested it worked. – Fewong Jun 7 '18 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).

|improve this answer|||||
  • nice suggestion – erTugRul May 16 '18 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

|improve this answer|||||
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]
|improve this answer|||||
  • 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). – Matija Nalis May 17 '18 at 14:41
  • 1
    @MatijaNalis: Very true! But you really wouldn't care for 5 files. – FloHimself May 18 '18 at 5:30
6

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

paste -s 2[0-8]_SumActive.txt
|improve this answer|||||
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.

|improve this answer|||||
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 ]
|improve this answer|||||
  • 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 '18 at 14:32
  • 2
    Or just cat "$i"; test -s "$i" || echo - no need for that unwieldy if or non-portable echo flags. – Toby Speight May 17 '18 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.

|improve this answer|||||
  • 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 '18 at 22:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for?Browse other questions tagged or ask your own question.