1

I'm sending commands via stdin, how can I send path arguments in a safe manner?

E.g.

stat /some strange/p"at\nh'/

fails because of the strange path. Could path be stored in a variable or other means and have it work? Or is there an easy way to escape these strange paths before sending them?

EDIT: to be more clear, the strange path can contain any valid posix filename characters so as an example handling the strange directory created below:

mkdir """
'''\n
"

closed as unclear what you're asking by Kusalananda, jimmij, Mr Shunz, Haxiel, Michael Homer Mar 7 at 19:32

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • 1
    Could you explain more? Is /some strange/p"at\nh'/ coming from a user argument? Is the second argument p"at\nh containing a new line in the middle? – Inian Mar 6 at 6:16
  • @Inian yes it could be coming from a user argument. The strange path can contain any valid posix file characters including new lines, quotes, spaces, etc. Tomasz solution below resolves some cases but does not work in all cases. – TrevTheDev Mar 7 at 3:28
  • The question is unclear: In the title you talk about "arguments", but in the text you talk about sending data on standard input. You will have to clarify what you are doing as these are very different things. – Kusalananda Mar 7 at 8:35
  • @Kulsalananda I am returning a list of files using stat **, I get the filenames and run lsattr <<filename>> - it works except with the strange filenames like the one shown. – TrevTheDev Mar 7 at 10:18
1

The difficult part is to define this strange path. Once you have it correct in the memory, you can do things with it. I'll use the here doc to grab it and I'll define it as some strange/p"at\nh'/ to be able to operate locally (no / at the beginning):

$ p="$(cat<<EOF
some strange/p"at\nh'/
EOF
)"
$ echo "$p"
some strange/p"at\nh'/
$ mkdir -p -- "$p"
tomasz@tomasz-laptop-f:~/x$ stat -- "$p"
  File: some strange/p"at\nh'/
  Size: 4096        Blocks: 8          IO Block: 4096   directory
Device: fe05h/65029d    Inode: 4983105     Links: 2
Access: (0755/drwxr-xr-x)  Uid: ( 1000/  tomasz)   Gid: ( 1000/  tomasz)
Access: 2019-03-06 08:50:05.116674683 +0100
Modify: 2019-03-06 08:50:05.116674683 +0100
Change: 2019-03-06 08:50:05.116674683 +0100
 Birth: -
  • Thank you @Tomasz for your answer which works for the specific strange path I provided, but your answer will not work in all cases - see my edit on the original question. – TrevTheDev Mar 7 at 4:07
  • @TrevTheDev You could break the lines in the here doc. Just a matter of manipulation. – Tomasz Mar 7 at 7:15
  • I think the heredoc is ok, but when one tries to use stat with the variable it does not play nice. – TrevTheDev Mar 7 at 7:38
  • @TrevTheDev It does play ok. But don't put \n in the here doc, only start a new line instead. – Tomasz Mar 7 at 8:12
  • other strange files work with your solution, but when my script hits files like this using your solution it fails - lsattr: No such file or directory while trying to stat. I'm getting the filename via stat **, then using it to run lsattr <<filename>> - if I use your solution most files are ok, but the example I've provided above still fails. I do not control whether \n is in my string - it comes from stat **. – TrevTheDev Mar 7 at 10:16
1

Provided you don't have too many files you can try expanding the ** in a loop, and passing that to stat and friends:

for item in **
do
    stat -- "$item"
    lsattr -- "$item"
done

Alternatively, you could use find -print0. This will allow you to capture a selection of filename matches and process them in multiple different ways:

find . -type f -print0 |
    while read -d $'\0' item
    do
        stat -- "$item"
        lsattr -- "$item"
    done

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