0

TL;DR I was writing a very simple bash script, which goes into each folder in my pwd and find for files with names pid. If yes, echo that file out.

pids=$(cat */*/bin/*pid)
echo $pids
>> 3742031 3741375 3741415 3742159 

The PIDs are nicely printed with spaces

I changed this code a bit to find PIDs in path:

pids=$(cat */*pid)
echo $pids
>> 37410543741078

Notice this time it was printed without spaces. Now all these files are auto generated by an application, so the way of storing these values must be consistent - with or without \n etc.

My question is with almost the same code, why in one case it concatenates the string with space and in the other case without space, how is it possible to get a more consistent behavior with cat? (not echo).

Adding the workaround:

Regardless of the file, I am appending a whitespace, before reading the file like: sed '$s/$/ /' */pid. This resolves the problem.

11
  • 1
    If you double-quote your variable, so you have echo "$pids", what do you get and does it shed any light on the issue? Commented Feb 14, 2020 at 22:58
  • 1
    Please show us the actual output. Don't fancy it up. Commented Feb 14, 2020 at 22:58
  • 1
    Show the actual output, separately from the commands, without your annotations. Also show separately what the files contain, also without extra annotation. Do they contain exactly the same thing in both examples (even whitespaces, like final newlines on the last line of the files)? Always double quote variable expansions (see When is double-quoting necessary?). This has nothing to do with cat but what's in your files.
    – Kusalananda
    Commented Feb 14, 2020 at 23:03
  • 1
    This is not an issue. The OP should provide a full script and a way to reproduce this. Those code snippets are not the whole story. For me, with a simple sample setup both versions output the same strings. Commented Feb 14, 2020 at 23:14
  • 2
    No path can match */*/bin/*pid and */*pid simultaneously. The simplest answer is you're reading different files and their general format in the first case is different than in the second case. The claim that "the way of storing these values must be consistent" is questionable. Bugs happen, quirks happen, inconsistent requirements happen. Commented Feb 15, 2020 at 5:46

1 Answer 1

0

The best way to find files is find command. For example:

for file in $(find / -type f -iname "*.pid"); do echo "$file = `cat $file | tr -d '\n'`"; done

Double quotation marks must be used to display the contents of a string variable. Otherwise, any special characters (such as operators) or strings resembling Shell commands can be understood as a real Shell command, and will of course be "executed" in Shell.

In the first case, you searched the directory where the ".pid" files found contained one special character (Unix newline code, Line Feed code, known also as the LF code). However, in the second case of your search, ".pid" files do not contain a special newline character at the end (files contain only a number as the string - and without ending a newline). Try to find and open the mentioned ".pid" files in hex editor and check the last character. The contents of your files may differ by the LF code at the end (0A in hex).

Some ".pid" files contain this LF code and some do not. It depends on how the files were created. For example, a standard echo command usually also adds this LF code at the end of line. However, you can also use the -n argument, which does not add this LF code to the end of the echo command output:

root@formuler3ip:~# echo "666" > /tmp/test1
root@formuler3ip:~# echo -n "666" > /tmp/test2
root@formuler3ip:~# xxd -g 1 /tmp/test1
00000000: 36 36 36 0a                                      666.
root@formuler3ip:~# xxd -g 1 /tmp/test2
00000000: 36 36 36                                         666

You must log in to answer this question.

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