-1

Wrapping quotes around dotfolders in the home folder breaks all shell commands, e.g.:

[jeff@mypc 0]$ 
[jeff@mypc 0]$ ls "~/.cache/"
ls: cannot access ~/.cache/: No such file or directory
[jeff@mypc 0]$ ls ~/.cache/
event-sound-cache.tdb.7187a0911f063e087eac3cc10000002b.x86_64-redhat-linux-gnu
mozilla
[jeff@mypc 0]$ 

Is there some escape sequence that I need to use?

I need to use quotes, because I am accessing subfolders which may contain spaces. I cannot expand the ~ shortcut to /home/jeff, because I need it to work for any user. I have other constraints that prevent me from using environment variables like $HOME or $USER.

Edit 1

Why can't I use $HOME? Intel fortran has some issues with it apparently:

      program mwe 

      implicit none

      character(len = :), allocatable :: f

      integer :: unit, io

      f = '"$HOME/.cache/test.txt"'

      print *, 'f = ', f

      open(file = f, newunit = unit, iostat = io) 

      print *, 'io = ', io  ! io = 29, i.e. file not found

      end program mwe 
Jeff Irwin
  • 1,021
  • 8
  • 11
  • Why in the world can't you use `"$HOME/.cache"`? Please describe these constraints in more detail -- if we understand why they exist, it may be possible to provide a workaround. – Charles Duffy Nov 15 '17 at 15:53
  • Note that if you run `HOME=/tmp; echo ~` you get `/tmp` -- so if you don't trust the value of `HOME`, you can't trust the behavior of `~` either. – Charles Duffy Nov 15 '17 at 15:55
  • See the edit regarding `$HOME`. It looks like your answer and the dupes will probably help. Sorry I didn't see the dupes, I wasn't searching for the right keywords. – Jeff Irwin Nov 15 '17 at 16:27
  • The syscalls used by programs to make requests of the operating system don't run expansions -- not `~`, not `$HOME`, etc -- so generally speaking, *all* of those are shell constructs, meaningless in Fortran, C, or otherwise absolutely anything that isn't a shell. That said, I'm not sure why Fortran *matters* in a question tagged `bash` -- if you're doing things right, you'll be passing your filename into your Fortran program as an argument *expanded by the shell* beforehand, so `$HOME` will have been changed to `/home/jeff` before the Fortran program started. – Charles Duffy Nov 15 '17 at 16:29
  • (For the same reasons, you probably shouldn't have literal double quotes inside your Fortran string -- those quotes have syntactic meaning to the shell, and aren't meaningful to anything else; if you're doing something awful, like generating shell scripts from Fortran -- or using `SYSTEM` -- the short answer is "don't" -- such practices are a major cause of security bugs, and otherwise full of subtle pitfalls). – Charles Duffy Nov 15 '17 at 16:31
  • 1
    ...that said, you should have `get_environment_variable()`, or be able to use C bindings to access `getenv()`, and be able to get to `HOME` that way. – Charles Duffy Nov 15 '17 at 16:39
  • I ended up using `get_environment_variable()`, things are working smoothly now. Unfortunately Fortran lacks virtually all filesystem operations, so `system()` is an ugly necessity. – Jeff Irwin Nov 15 '17 at 20:07
  • 1
    The baseline essentials are `FORK`, `EXECVE` and `WAITPID`. If you've got those, you can build whatever you need on top of 'em. Even if you're starting a shell script, using `EXECVE` lets you pass arguments out-of-band: `execve(['sh', '-c', 'script that uses "$1"', '_', 'string for $1'])` is far safer than `system('script that uses \'string for $1\'')`. – Charles Duffy Nov 15 '17 at 20:38

1 Answers1

2

Quoting a ~ prevents it from being expanded by the shell. It's only that specific character that needs to be left unquoted:

ls ~"/.cache/"

Best practice is to use "$HOME/.cache" instead.

Charles Duffy
  • 235,655
  • 34
  • 305
  • 356