I have some Python scripts, that I keep in a repository; they are plain-text files, but if their executable bit is set, then the online repository page serves them as binary downloads, not as plain text pages. Thus, I'd prefer to keep these scripts non-executable.

However, I'd also like to use them, as well. In principle, I could do:

sudo ln -s /path/to/wherever/I/have/put/myscript.py /usr/bin/

... and then, if the script was executable (and has a shebang), I could just call on the command line:

myscript.py [ARGS]

... which is what I'd want. But if I make the script itself executable, then I have the repository download problem as stated above. And, as long as the script is non-executable, I'd have to call it with an extra python - and a which ( cause otherwise python would just look in the current directory for the file):

python `which myscript.py` [ARGS]

... which is still quite a bit of typing, which I don't like. Also, as long-as the file is non-executable, not even tab completion will work for my[TAB] even if it is in /usr/bin; only which will work.

Now, crudely - if I could have a separate, executable permissions on the symlink, I could hope to keep the original non-executable, and still be able to run directly via just myscript.py on the command line. I'm not sure if there is possibility for Mac OSX - but as How do file permissions apply to symlinks? - Super User notes, Linux definitely doesn't offer options for that: only the original file permissions are taken into account, the permission of the symlink itself isn't.

So I was wondering:

  • Is it possible to use a different type of link (maybe "hard link"?) for that kind of purpose?
  • Is there some kind of driver or software, which would basically allow you to make something akin to a symlink, but would be an identical copy of the source - except with its own set of permissions?

A symlink won't work. A hard link (when possible) won't work either because both files will have the same permissions. But I'd do the following: instead of a link, write a shell script /usr/bin/myscript.py that executes the script itself:

exec python /path/to/wherever/I/have/put/myscript.py "$@"

The "$@" passes any parameters through; if your script does not accept any parameters, you can safely remove that part.

  • 1
    This was going to be my answer, too. I added $* for parameter passing; hope you don't mind, vinc17.
    – user
    Nov 28 '14 at 19:30
  • 1
    @MichaelKjörling Thanks, I've corrected it to "$@" to support parameters with spaces.
    – vinc17
    Nov 28 '14 at 19:48
  • 1
    Even better! :) (Actually, I don't think you need the exec part, but...)
    – user
    Nov 28 '14 at 19:50
  • 1
    @MichaelKjörling The exec part is an optimization for some sh implementations to avoid leaving a sh process while the python script is being executed: not all shells detect that's the last command.
    – vinc17
    Nov 28 '14 at 19:55
  • Thanks for that @vinc17, very nice approach; another alternative I forgot while writing the OP, was to include alias myscript.py="python /path/to../myscript.py" in .bashrc. Cheers!
    – sdaau
    Nov 28 '14 at 22:05

A symbolic link doesn't affect the permissions of its target, it's just a way to store a path that's followed automatically by the kernel. In fact, many systems ignore the permissions of symbolic links altogether.

A hard link wouldn't help you since that's a way to have the same file (same content, same metadata including permissions) at several locations in the filesystem.

You can use bindfs to create an alternate view of a filesystem where files have a different permission.

bindfs --perms=a+x /path/to/wherever/I/have/put ~/bin/wherever

That would make all the files in the alternate view executable. It's probably not a convenient method in your case but may be useful to others with a similar problem.

The real solution for you would be to fix the repository system so that it doesn't care about permissions, assuming that the download system is able to make files executable. Failing that, what I would do is to change the files' permission after downloading.

chmod +x /path/to/wherever/I/have/put/*.py

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.