3

I have a file named test's file.txt inside test's dir directory. So the file-path becomes test's dir/test's file.txt. I want to cat the content of the file but since the file contains an apostrophe and a space it is giving me hard time achieving that. I have tried several commands including

  1. sh -c "cat 'test's dir/test's file.txt'"
  2. sh -c 'cat "test's dir/test's file.txt"'
  3. sh -c "cat '"'"'test's dir/test's file.txt'"'"'"
  4. sh -c 'cat "test\'s\ dir/test\'s\ file.txt"' and many more ... But none of them is working.

Some help would be really appreciated. Thank you!

anubhava
  • 761,203
  • 64
  • 569
  • 643
  • 2
    Is there a particular reason, why you want to do a `sh -c` to do this, instead of invoking `cat` directly? – user1934428 Mar 02 '22 at 08:05
  • 1
    Using `sh -c` requires adding a second layer of quoting/escaping, which complicates the syntax quite a lot. To run the `cat` command directly (without `sh -c`), you could just use double-quotes: `cat "test's dir/test's file.txt"`. – Gordon Davisson Mar 02 '22 at 10:54
  • See [How to have simple and double quotes in a scripted ssh command](https://stackoverflow.com/q/45308395/4154375) for good information about quoting commands for later evaluation (by `ssh`, `eval`, `sh -c`, ...). – pjh Mar 02 '22 at 12:42
  • Apart from an academic exercise, is there a good reason to have file or directory names with either spaces or quotes (single or double — or back) in the name? – Jonathan Leffler Mar 02 '22 at 15:25
  • @JonathanLeffler I mostly use macOS, so spaces (and other funny characters) in filenames are just facts of life. Any script or program that can't handle them is going to cause trouble. (More generally, most GUI users aren't aware of what characters are hard to deal with at the command line, so you can't expect them to avoid such characters.) – Gordon Davisson Mar 04 '22 at 02:52

3 Answers3

2

You can use here-doc:

sh -s <<-'EOF'
cat "test's dir/test's file.txt"
EOF
anubhava
  • 761,203
  • 64
  • 569
  • 643
  • 1
    Hi @anubhava, yes this worked for me. Thanks a lot for the quick help. But I was looking for a one line solution for this with limited changes. But this is good stuff, learned something new today. – Hitesh Paryani Mar 02 '22 at 08:41
2

Would you please try:

sh -c "cat 'test'\''s dir/test'\''s file.txt'"

As for the pathname part, it is a concatenation of:

'test'
\'
's dir/test'
\'
's file.txt'

[Edit]
If you want to execute the shell command in python, would you please try:

#!/usr/bin/python3

import subprocess

path="test's dir/test's file.txt"
subprocess.run(['cat', path])

or immediately:

subprocess.run(['cat', "test's dir/test's file.txt"])

As the subprocess.run() function takes the command as a list, not a single string (possible with shell=True option), we do not have to worry about the extra quoting around the command.

Please note subprocess.run() is supported by Python 3.5 or newer.

tshiono
  • 21,248
  • 2
  • 14
  • 22
  • This is great @tshiono, this solution looks perfect for my problem. Thanks a lot, appreciate the quick help :) – Hitesh Paryani Mar 02 '22 at 08:42
  • Is there any python library that handles such cases? – Hitesh Paryani Mar 02 '22 at 08:44
  • Thank you for the feedback. If you think your problem is solved, I'd be pleased if you can accept the answer by clicking the check mark beside the answer – tshiono Mar 02 '22 at 09:10
  • As for python, do you want to invoke shell command from within the python script? – tshiono Mar 02 '22 at 09:11
  • Yes, I'll be executing this command via shell executer. But I wanted to check if there's a python library which can re-format the command to handle such cases (quotes, spaces) – Hitesh Paryani Mar 02 '22 at 09:17
  • I've updated my answer with a python version. If it is not what you expect, please elaborate about what you want to execute and the problem. – tshiono Mar 02 '22 at 10:36
0

This option avoids the need for two levels of quoting:

sh -c 'cat -- "$0"' "test's dir/test's file.txt"

See How to use positional parameters with "bash -c" command?. (It applies to sh -c too.)

pjh
  • 6,388
  • 2
  • 16
  • 17