11

I have an entire folder dedicated to python scripts.

I'm tired of doing chmod on every new python script that I write.

Is there a way to make every file inside my folder executable if it is a python script?

It would be nice to have a script that checks whenever a new .py script is created and if there is a new .py script make it executable right there on the spot.

  • I use Vim.
  • What do you use to write these scripts? It would be possible to configure vim or emacs to do that for you. – muru Nov 6 '14 at 4:21
  • I use vim. And that would be perfect. – Dominici Nov 6 '14 at 4:52
  • are there subfolders in the directory? – Jacob Vlijm Nov 6 '14 at 8:39
  • No subfolders just my scripts. – Dominici Nov 6 '14 at 19:04
10

Another good option is Incron. It works on inotify with specifiable conditions for a given location.

So I can say watch this folder, when you see a file created, run a command.

Just as a sample incrontab...

/path/to/scripts IN_CREATE chmod +x $@$#  # <--- this arcane bit is path ($@) + file ($#)

One could similarly use the path/file as arguments to a bash script to allow it to filter by .py extensions if needed.

  • Not sure if people ever come back to already answered questions to say thanks... but anyway. I'm new here, who cares. Thank you so freaking much. I'm using incron for pretty much all of the things I'm working on right now. – Dominici Nov 15 '14 at 3:43
  • No worries, glade it has been useful. :) The project is kind of obscure, so I like sharing it with people. I've made great use of it to automate and pipeline all sorts of things. – DivinusVox Nov 15 '14 at 6:05
4
chmod +x /path/to/python/scripts/dir/*.py 

Will make executable all current .py files in directory /path/to/python/scripts/dir.

I'm not aware of an auto-tool as you describe. It might be possible to have a macro in your editor that could do this, but not with the editor I use. ;-)

  • 4
    thanks for the pointers. The O.P. specifically said python scripts, so that is why I include *.py. I'm also assuming that the O.P.s scripts are owned by his standard userID, so I don't see the need for sudo. Good luck to all. – shellter Nov 6 '14 at 4:19
1

As a first step, you could try this in your ~/.vimrc:

autocmd BufWritePost *.py silent execute "! chmod +x %"
  • This runs chmod +x on the filename for all .py files when you write to them. Looking at the list of events (:h events), I can't find an event where a new file is created, so I had to settle for running each time it is written to.
  • The first time the chmod is applied, the file gets changed, and vim will alert you to that:

    "test.py" [New] 0L, 0C written
    W16: Warning: Mode of file "test.py" has changed since editing started
    See ":help W16" for more info.
    [O]K, (L)oad File:
    

    I tried a couple of tricks to make it autoread just for this change, but no luck. So you'll have to press Enter twice.

1

When initiated, the script below automatically changes the permissions of all files of a given type (extension) in a directory (one time). After that, the script checks the directory every 5 seconds for newly added files, and changes the permissions if the file is of the given type (in this case a .py file)

It has a few options: in this case, it makes the newly added files executable, but other actions are possible too, as defined in the line: command = "chmod +x". Additionally, you can define (change) on what kind of files (language extensions) the action should be performed.

How to use

Copy the script below into an empty file. Save it as change_permission.py and run it in the background by the command:

python3 <script> <folder_to_watch>

The script

#!/usr/bin/env python3

import subprocess
import time
import sys

directory = sys.argv[1]
command = "chmod +x"; check_interval = 5; extensions = (".py")

def current_files():
    read = subprocess.check_output(["ls", directory]).decode("utf-8").strip()
    return [item for item in read.split("\n") if item[item.rfind("."):] in extensions]

initial_files = current_files()
for file in initial_files:
    subprocess.call(["/bin/bash", "-c", command+" "+directory+"/"+file])

while True:
    update = current_files()
    for file in update:
        if not file in initial_files:
            subprocess.call(["/bin/bash", "-c", command+" "+directory+"/"+file])  
    initial_files = update
    time.sleep(check_interval)

*Note: if you need sudo privileges, simply run the script with sudo

1

Here is some info with a few commands that might help, check out http://ss64.com/bash/syntax-permissions.html

find . -type f -print0 | xargs -0 chmod 775 # change all file permissions in current directory

find . -type d -print0 | xargs -0 chmod 755 # change directory permissions

You could use the following header script. Place mkscript.sh in your $PATH. Execute mkscript.sh from the working directory where the python scripts are stored. The script creates some useful header info, titles the script and makes it executable, and then opens the chosen editor; in your case VIM.

I modified mkscript.sh, it will produce scripts with the python extension *.py

The variable ${PYTHON_VERSION} is called, so PYTHON_VERSION="/usr/bin/python --version" has been added to the /etc/environment file. Have a look at https://help.ubuntu.com/community/EnvironmentVariables

#!/bin/bash -       
#title           :mkscript.sh
#description     :This script will make a header for a PYTHON script.
#author      :bgw
#date            :20111101
#version         :0.4    
#usage       :bash mkscript.sh
#notes           :Install Vim and Emacs to use this script.
#bash_version    :4.1.5(1)-release
#==============================================================================

today=$(date +%Y%m%d)
div=======================================

/usr/bin/clear

_select_title(){

    # Get the user input.
    printf "Enter a title: " ; read -r title

    # Remove the spaces from the title if necessary.
    title=${title// /_}

    # Convert uppercase to lowercase.
    title=${title,,}

    # Add .sh to the end of the title if it is not there already.
    [ "${title: -3}" != '.py' ] && title=${title}.py

    # Check to see if the file exists already.
    if [ -e $title ] ; then 
        printf "\n%s\n%s\n\n" "The script \"$title\" already exists." \
        "Please select another title."
        _select_title
    fi

}

_select_title

printf "Enter a description: " ; read -r dscrpt
printf "Enter your name: " ; read -r name
printf "Enter the version number: " ; read -r vnum

# Format the output and write it to a file.
printf "%-16s\n\
%-16s%-8s\n\
%-16s%-8s\n\
%-16s%-8s\n\
%-16s%-8s\n\
%-16s%-8s\n\
%-16s%-8s\n\
%-16s%-8s\n\
%-16s%-8s\n\
%s\n\n\n" '#!/usr/bin/python -' '#title' ":$title" '#description' \
":${dscrpt}" '#author' ":$name" '#date' ":$today" '#version' \
":$vnum" '#usage' ":./$title" '#notes' ':' '#python_version' \
":${PYTHON_VERSION}" \#$div${div} > $title

# Make the file executable.
chmod +x $title

/usr/bin/clear

_select_editor(){

    # Select between Vim or Emacs.
    printf "%s\n%s\n%s\n\n" "Select an editor." "1 for Vim." "2 for Emacs."
    read -r editor

    # Open the file with the cursor on the twelth line.
    case $editor in
        1) vim +12 $title
            ;;
        2) emacs +12 $title &
            ;;
        *) /usr/bin/clear
           printf "%s\n%s\n\n" "I did not understand your selection." \
               "Press <Ctrl-c> to quit."
           _select_editor
            ;;
    esac

}

_select_editor

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.