Suppose I have a python script called a.py like this:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Author : Bhishan Poudel
# Date : Jul 13, 2016
# Imports
# Script
print("hello")
I can run this scripts in two ways:
Using python interpreter:
python3 a.py
Changing permission
chmod a+x a.py; ./a.py
QUESTION
How can I run any new or old python scripts without using chmod a+x script_name all the times.
I have root access and user access both to my computer.
Basically i want executable permission to all the .py files, how can we do so?
I tried different shebangs such as:
#!/usr/bin/python3
#!/usr/bin/env python3
#!/usr/local/bin/python3
#!/usr/local/bin/env python3
The python interpreter is also in the $PATH.
The output of echo $PATH is following:
/Library/Frameworks/Python.framework/Versions/2.7/bin:/Library/Frameworks/Python.framework/Versions/3.5/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/opt/X11/bin:/usr/texbin:/Library/Frameworks/Python.framework/Versions/2.7/bin:/Library/Frameworks/Python.framework/Versions/3.5/bin:/opt/local/bin:/Users/poudel/phosim:/Users/poudel/Applications:/usr/local/octave/3.8.0/bin:/Users/poudel/Applications/Geany.app/Contents/MacOS/:/opt/local/bin:/Users/poudel/phosim:/Users/poudel/Applications:/usr/local/octave/3.8.0/bin:/Applications/Geany.app/Contents/MacOS/:/opt/local/bin:/Users/poudel/phosim:/Users/poudel/Applications:/usr/local/octave/3.8.0/bin:/Applications/Geany.app/Contents/MacOS/
Also, ls /usr/bin/py* has:
/usr/bin/pydoc* /usr/bin/python2.5# /usr/bin/pythonw*
/usr/bin/pydoc2.5# /usr/bin/python2.5-config# /usr/bin/pythonw2.5#
/usr/bin/pydoc2.6# /usr/bin/python2.6# /usr/bin/pythonw2.6#
/usr/bin/pydoc2.7# /usr/bin/python2.6-config# /usr/bin/pythonw2.7#
/usr/bin/python* /usr/bin/python2.7#
/usr/bin/python-config* /usr/bin/python2.7-config#
Related links:
http://effbot.org/pyfaq/how-do-i-make-a-python-script-executable-on-unix.htm
Permission Denied when executing python file in linux
bash permission denied for python
Permission denied when launch python script via bash
The hard way
Run below with root privilege:
find /your/path/ -type f -name "*.py" -exec chmod u+x {} \;
Note:
chmod need not be run as root if you're the owner of .py file.
The smart way
Write a script to take care of this.
#!/bin/bash
if [ -f "$1" ]
then
geany "$1" # You could also use xdg-open if you set geany to open .py files
else
cp /path/to/python/startup/template "$1" # You may omit this if you don't have a default template
chmod u+x "$1"
geany "$1"
fi
Save the script as, say, pycreator in say /usr/bin/ , then do
chown root:root /usr/bin/pycreator
chmod +x-w /usr/bin/pycreator
To create a new script using pycreator, do
pycreator calculator.py
Also [ this ] answer pointed to by #choroba in his comment provides valuable insight in this regard.
Using the idea of #sjsam,
I did following:
Suppose I have a file hello.py in any location.
cd to that location
find $PWD -type f -name "*.py" -exec chmod u+x {} \;
./hello.py
# Now, i can create any number of .py files in that folder and run ./filename
# Note: if we are running as user permission, and also have sudo access,
we can also do:
sudo -H find $PWD -type f -name "*.py" -exec chmod u+x {} \;
We should not use sudo unless absolutely necessary.
Thanks to sjsam.
Just type this command in terminal.
sudo su
Try this chmod +x *.py it works on my PC(OS:Ubuntu 20.4), Also i am using #! /usr/bin/env python3 shebang
Related
I have a shell script which I want to run without using the "sh" or "bash" commands. For example:
Instead of: sh script.sh
I want to use: script.sh
How can I do this?
P.S. (i) I don't use shell script much and I tried reading about aliases, but I did not understand how to use them.
(ii) I also read about linking the script with another file in the PATH variables. I am using my university server and I don't have permissions to create a file in those locations.
Add a "shebang" at the top of your file:
#!/bin/bash
And make your file executable (chmod +x script.sh).
Finally, modify your path to add the directory where your script is located:
export PATH=$PATH:/appropriate/directory
(typically, you want $HOME/bin for storing your own scripts)
These are the prerequisites of directly using the script name:
Add the shebang line (#!/bin/bash) at the very top.
Use chmod u+x scriptname to make the script executable (where scriptname is the name of your script).
Place the script under /usr/local/bin folder.
Note: I suggest placing it under /usr/local/bin because most likely that path will be already added to your PATH variable.
Run the script using just its name, scriptname.
If you don't have access to /usr/local/bin then do the following:
Create a folder in your home directory and call it bin.
Do ls -lA on your home directory, to identify the start-up script your shell is using. It should be either .profile or .bashrc.
Once you have identified the start up script, add the following line:
PATH="$PATH:$HOME/bin"
Once added, source your start-up script or log out and log back in.
To source, put . followed by a space and then your start-up script name, e.g. . .profile or . .bashrc
Run the script using just its name, scriptname.
Just make sure it is executable, using chmod +x. By default, the current directory is not on your PATH, so you will need to execute it as ./script.sh - or otherwise reference it by a qualified path. Alternatively, if you truly need just script.sh, you would need to add it to your PATH. (You may not have access to modify the system path, but you can almost certainly modify the PATH of your own current environment.) This also assumes that your script starts with something like #!/bin/sh.
You could also still use an alias, which is not really related to shell scripting but just the shell, and is simple as:
alias script.sh='sh script.sh'
Which would allow you to use just simply script.sh (literally - this won't work for any other *.sh file) instead of sh script.sh.
In this example the file will be called myShell
First of all we will need to make this file we can just start off by typing the following:
sudo nano myShell
Notice we didn't put the .sh extension?
That's because when we run it from the terminal we will only need to type myShell in order to run our command!
Now, in nano the top line MUST be #!/bin/bash then you may leave a new line before continuing.
For demonstration I will add a basic Hello World! response
So, I type the following:
echo Hello World!
After that my example should look like this:
#!/bin/bash
echo Hello World!
Now save the file and then run this command:
chmod +x myShell
Now we have made the file executable we can move it to /usr/bin/ by using the following command:
sudo cp myShell /usr/bin/
Congrats! Our command is now done! In the terminal we can type myShell and it should say Hello World!
You have to enable the executable bit for the program.
chmod +x script.sh
Then you can use ./script.sh
You can add the folder to the PATH in your .bashrc file (located in your home directory).
Add this line to the end of the file:
export PATH=$PATH:/your/folder/here
You can type sudo install (name of script) /usr/local/bin/(what you want to type to execute said script)
ex: sudo install quickcommit.sh /usr/local/bin/quickcommit
enter password
now can run without .sh and in any directory
Add . (current directory) to your PATH variable.
You can do this by editing your .profile file.
put following line in your .profile file
PATH=$PATH:.
Just make sure to add Shebang (#!/bin/bash) line at the starting of your script and make the script executable(using chmod +x <File Name>).
Here is my backup script that will give you the idea and the automation:
Server: Ubuntu 16.04
PHP: 7.0
Apache2, Mysql etc...
# Make Shell Backup Script - Bash Backup Script
nano /home/user/bash/backupscript.sh
#!/bin/bash
# Backup All Start
mkdir /home/user/backup/$(date +"%Y-%m-%d")
sudo zip -ry /home/user/backup/$(date +"%Y-%m-%d")/etc_rest.zip /etc -x "*apache2*" -x "*php*" -x "*mysql*"
sudo zip -ry /home/user/backup/$(date +"%Y-%m-%d")/etc_apache2.zip /etc/apache2
sudo zip -ry /home/user/backup/$(date +"%Y-%m-%d")/etc_php.zip /etc/php
sudo zip -ry /home/user/backup/$(date +"%Y-%m-%d")/etc_mysql.zip /etc/mysql
sudo zip -ry /home/user/backup/$(date +"%Y-%m-%d")/var_www_rest.zip /var/www -x "*html*"
sudo zip -ry /home/user/backup/$(date +"%Y-%m-%d")/var_www_html.zip /var/www/html
sudo zip -ry /home/user/backup/$(date +"%Y-%m-%d")/home_user.zip /home/user -x "*backup*"
# Backup All End
echo "Backup Completed Successfully!"
echo "Location: /home/user/backup/$(date +"%Y-%m-%d")"
chmod +x /home/user/bash/backupscript.sh
sudo ln -s /home/user/bash/backupscript.sh /usr/bin/backupscript
change /home/user to your user directory and type: backupscript anywhere on terminal to run the script! (assuming that /usr/bin is in your path)
Enter "#!/bin/sh" before script.
Then save it as script.sh for example.
copy it to $HOME/bin or $HOME/usr/bin
The directory can be different on different linux distros but they end with 'bin' and are in home directory
cd $HOME/bin or $HOME/usr/bin
Type chmod 700 script.sh
And you can run it just by typing run.sh on terminal.
If it not work, try chmod +x run.sh instead of chmod 700 run.sh
Make any file as executable
Let's say you have an executable file called migrate_linux_amd64 and you want to run this file as a command like "migrate"
First test the executable file from the file location:
[oracle#localhost]$ ./migrate.linux-amd64
Usage: migrate OPTIONS COMMAND [arg...]
migrate [ -version | -help ]
Options:
-source Location of the migrations (driver://url)
-path Shorthand for -source=file://path
-database Run migrations against this database (driver://url)
-prefetch N Number of migrations to load in advance before executing (default 10)
-lock-timeout N Allow N seconds to acquire database lock (default 15)
-verbose Print verbose logging
-version Print version
-help Print usage
Commands:
goto V Migrate to version V
up [N] Apply all or N up migrations
down [N] Apply all or N down migrations
drop Drop everyting inside database
force V Set version V but don't run migration (ignores dirty state)
version Print current migration version
Make sure you have execute privileges on the file
-rwxr-xr-x 1 oracle oinstall 7473971 May 18 2017 migrate.linux-amd64
if not, run chmod +x migrate.linux-amd64
Then copy your file to /usr/local/bin. This directory is owned by root, use sudo or switch to root and perform the following operation
sudo cp migrate.linux-amd64 /usr/local/bin
sudo chown oracle:oracle /user/local/bin/migrate.linux.amd64
Then create a symbolic link like below
sudo ln /usr/local/bin/migrate.linux.amd64 /usr/local/bin/migrate
sudo chown oracle:oracle /usr/local/bin/migrate
Finally add /usr/local/bin to your path or user profile
export PATH = $PATH:/usr/local/bin
Then run the command as "migrate"
[oracle#localhost]$ migrate
Usage: migrate OPTIONS COMMAND [arg...]
migrate [ -version | -help ]
Options:
-source Location of the migrations (driver://url)
-path Shorthand for -source=file://path
-database Run migrations against this database (driver://url)
-prefetch N Number of migrations to load in advance before executing (default 10)
-lock-timeout N Allow N seconds to acquire database lock (default 15)
-verbose Print verbose logging
-version Print version
-help Print usage
Commands:
goto V Migrate to version V
up [N] Apply all or N up migrations
down [N] Apply all or N down migrations
drop Drop everyting inside database
force V Set version V but don't run migration (ignores dirty state)
version Print current migration version
Make the script file as executable by using file's properties
Create alias for the executable in ~/.bashrc. alias <alias namme> = <full script file path>'
refresh the user session to apply it. source ~/.bashrc
Just to add to what everyone suggested. Even with those solutions, the problem will persist if the user wants to execute the script as sudo
example:
chmod a+x /tmp/myscript.sh
sudo ln -s /tmp/myscript.sh /usr/local/bin/myscript
typing myscript would work but typing sudo myscript would return command not found.
As sudo you would have to still type sudo sh myscript or sudo bash myscript.
I can't think of a solution around this.
Just:
/path/to/file/my_script.sh
I am trying to run my python script without writing python func.py.
I've added to my script file #!/usr/bin/python2.7
did chmod +x func.py
when I try to run: ./func.py -p show -c all
the script works fine but if I try to take off the "flags" (-p , -c) or the "./" or ".py" it won't work.
taking flags off returns:
[root#pg66 tmp]# ./func.py show all
usage: func.py [-h] [-p PROCESS] [-c CLUSTER] [-t TYPE]
func.py: error: unrecognized arguments: show all
taking "./" & ".py" off returns:
[root#pg66 tmp]# func.py -p show -c all
-bash: func.py: command not found
edit: i have 3 flags -p -c -t , dont know where the -h came from. -t can be null so when i write -p show -c all it works.
you can simply use the chmod +* x in the location with the python file. This makes it easier for linux/unix After that you can run it by ./main.py Assuming the file is named as main.py. You can also remove the .py extension then give the permission by chmod +* x and after that then just execute by ./main. Another way to do this is simply going to the execution script of your terminal then add an alias for directly running the script just by typing the alias name
I made directories with file mode by mkdir in bash and os.mkdir in python.
They made directories with different permissions.
My test code in command line is following,
$ mkdir -m 0775 aaa
$ cd aaa
$ mkdir -m 0777 bbb
$ python -c 'import os; os.mkdir("ccc",0o777)'
The permission of directories, aaa, bbb and ccc are following
directory aaa: drwxrwxr-x
directory bbb: drwxrwxrwx
directory ccc: drwxrwxr-x
It seems that mkdir in bash does not care the permission of parent directory but os.mkdir in python does. Is it right?
And why do they have different mechanism?
Thank you very much.
mkdir(1) is temporarily setting the umask to 0 if you specify a mode, as cryptically documented in the manual:
-m, --mode=MODE
set file mode (as in chmod), not a=rwx - umask
Python is just calling the mkdir(2) syscall with the mode given and the usual umask behavior.
The equivalent Python code to what mkdir(1) is doing:
m = os.umask(0)
os.mkdir("ccc")
os.umask(m)
noobiest question ever:
I'm trying to work with python via cygwin on my pc laptop - I have a file (foo.py) but python can't find it. The error it's giving me is:
$ chmod +x foo.py
chmod: cannot access `foo.py': No such file or directory
Is there a special location within the Cygwin folder that I need to save my foo.py?
Thanks!
AP
It's not python that can't find your file, it's the chmod command. C drive is mapped to /cygdrive/c in Cygwin, and D drive is mapped to /cygdrive/d and so on and so forth.
Are you in the same directory as the file when you are running chmod?
If your file is at C:\mycode\python\foo.py then you should either change to that directory first -
$ cd c:
$ cd mycode/python/
or as #Ahmed mentioned above, you could also run the command as
$ chmod +x /cygdrive/c/mycode/python/foo.py
But you only need chmod if your python script starts with
#!/bin/python
To execute such a file, you'd say
$ /cygdrive/c/mycode/python/foo.py
Or if you are in the same directory
./foo.py
If the first line of the python script isn't "#!/bin/python" then you can skip the chmod and just type
python /cygdrive/c/mycode/python/foo.py
You go right click on foo.py figure out its full path then do this:
chmod +x foos-full-directory/foo.py
And this should work for you and btw its not Python problem it's your pwd other than the foo.py working directory and you even didn't use python word in your command.
If I have a basic Python script, with it's hashbang and what-not in place, so that from the terminal on Linux I can run
/path/to/file/MyScript [args]
without executing through the interpreter or any file extensions, and it will execute the program.
So would I install this script so that I can type simply
MyScript [args]
anywhere in the system and it will run? Can this be implemented for all users on the system, or must it be redone for each one? Do I simply place the script in a specific directory, or are other things necessary?
The best place to put things like this is /usr/local/bin.
This is the normal place to put custom installed binaries, and should be early in your PATH.
Simply copy the script there (probably using sudo), and it should work for any user.
Walkthrough of making a python script available anywhere:
Make a python script:
cd /home/el/bin
touch stuff.py
chmod +x stuff.py
Find out where your python is:
which python
/usr/bin/python
Put this code in there:
#!/usr/bin/python
print "hi"
Run in it the same directory:
python stuff.py
Go up a directory and it's not available:
cd ..
stuff.py
-bash: stuff.py: command not found
Not found! It's as we expect, add the file path of the python file to the $PATH
vi ~/.bashrc
Add the file:
export PATH=$PATH:/home/el/bin
Save it out, re apply the .bashrc, and retry
source ~/.bashrc
Try again:
cd /home/el
stuff.py
Prints:
hi
The trick is that the bash shell knows the language of the file via the shebang.
you can also use setuptools (https://pypi.org/project/setuptools/)
your script will be:
def hi():
print("hi")
(suppose the file name is hello.py)
also add __init__.py file next to your script (with nothing in it).
add setup.py script, with the content:
#!/usr/bin/env python3
import setuptools
install_requires = [
'WHATEVER PACKAGES YOU NEED GOES HERE'
]
setuptools.setup(
name="some_utils",
version="1.1",
packages=setuptools.find_packages(),
install_requires=install_requires,
entry_points={
'console_scripts': [
'cool_script = hello:hi',
],
},
include_package_data=True,
)
you can now run python setup.py develop in this folder
then from anywhere, run cool_script and your script will run.
Just create ~/bin and put export PATH=$PATH:$HOME/bin in your bashrc/profile. Don't mess with the system, it will bite you back, trust me.
Few more things (relevant to the question but not part of the answer):
The other way export PATH=$HOME/bin:$PATH is NOT safe, for bash will will look into your ~/bin folder for executables, and if their name matches with other executables in your original $PATH you will be surprised by unexpected/non working command execution.
Don't forget to chmod+x when you save your script in ~/bin.
Be aware of what you are putting in your ~/bin folder, if you are just testing something or working on unfinished script, its always better to use ./$SCRIPT_NAME from your CWD to execute the script than putting it under ~/bin.
The quick answer is to symlink your script to any directory included in your system $PATH.
The long answer is described below with a walk through example, (this is what I normally do):
a) Create the script e.g. $HOME/Desktop/myscript.py:
#!/usr/bin/python
print("Hello Pythonista!")
b) Change the permission of the script file to make it executable:
$ chmod +x myscript.py
c) Add a customized directory to the $PATH (see why in the notes below) to use it for the user's scripts:
$ export PATH="$PATH:$HOME/bin"
d) Create a symbolic link to the script as follows:
$ ln -s $HOME/Desktop/myscript.py $HOME/bin/hello
Notice that hello (can be anything) is the name of the command that you will use to invoke your script.
Note:
i) The reason to use $HOME/bin instead of the /usr/local/bin is to separate the local scripts from those of other users (if you wish to) and other installed stuff.
ii) To create a symlink you should use the complete correct path, i.e.
$HOME/bin GOOD ~/bin NO GOOD!
Here is a complete example:
$ pwd
~/Desktop
$ cat > myscript.py << EOF
> #!/usr/bin/python
> print("Hello Pythonista!")
> EOF
$ export PATH="$PATH:$HOME/bin"
$ ln -s $HOME/Desktop/myscript.py $HOME/bin/hello
$ chmod +x myscript.py
$ hello
Hello Pythonista!
Just create symbolic link to your script in /usr/local/bin/:
sudo ln -s /path/to/your/script.py /usr/local/bin/script
Putting the script somewhere in the PATH (like /usr/local/bin) is a good solution, but this forces all the users of your system to use/see your script.
Adding an alias in /etc/profile could be a way to do what you want allowing the users of your system to undo this using the unalias command. The line to be added would be:
alias MyScript=/path/to/file/MyScript
i find a simple alias in my ~/.bash_profile or ~/.zshrc is the easiest:
alias myscript="python path/to/my/script.py"
Type echo $PATH in a shell. Those are the directories searched when you type command, so put it in one of those.
Edit: Apparently don't use /usr/bin, use /usr/local/bin
Acording to FHS, the /usr/local/bin/ is the good place for custom scripts.
I prefer to make them 755 root:root, after copying them there.