I put a python script to my /usr/local/bin to use as a command in bash.
I want to use my bash working directory, but I only get the current directory where the script is executed.
Is there a way to use the current directory as a command does?
E.g. with convert2ogg (as python script in /usr/local/bin)
$ cd ~/Music
$ convert2ogg *.mp3
import os,sys
print("CWD: "+os.getcwd())
print("Script: "+sys.argv[0])
print(".EXE: "+os.path.dirname(sys.executable))
print("Script dir: "+ os.path.realpath(os.path.dirname(sys.argv[0])))
pathname, scriptname = os.path.split(sys.argv[0])
print("Relative script dir: "+pathname)
print("Script dir: "+ os.path.abspath(pathname))
This code was very clear for me. os.path was not the solution for all my problems ;) I look for an answer, and seems anybody ask it before. The first line with os.getcwd() solved my problem.
Related
[Introduction]
Hi! I'm working on a python script to automate installation of UWP-Apps, it's been a long time i'm not touching Python; until this day. The script uses Depedencies inside the script directory, i've looking up on my older scripts and found this specific code.
os.chdir(os.path.dirname(sys.argv[0]))
[Problematic]
However, using the above code doesn't work on my current script but it's working fine on older scripts. When using above, it shows:
OSError: [WinError 123] The filename, directory name, or volume label syntax is incorrect: ''
Already looking up on Internet about this topic; but most of them was talking about running the script from outer/different directory that leads me to dead end.
Any helps is appreciated :)
The easiest answer is probably to change your working directory, then call the .py file from where it is:
cd path/to/python/file && python ../.py
Of course you might find it even easier to write a script that does it all for you, like so:
Save this as runPython.sh in the directory where you're running the python script from, is:
#!/bin/sh
cd path/to/python/file
python ../script.py
Make it executable (for yourself):
chmod +x ./runPython.sh
Then you can simply enter your directory and run it:
./runPython.sh
If you want to only make changes to the python script:
mydir = os.getcwd() # would be the folder where you're running the file
mydir_tmp = "path/to/python/file" # get the path
mydir_new = os.chdir(mydir_tmp) # change the current working directory
mydir = os.getcwd()
The reason you got an error was because sys.argv[0] is the name of the file itself, instead you can pass the directory as a string and use sys.argv[1] instead.
import os
from os.path import abspath, dirname
os.chdir(dirname(abspath(__file__)))
You can use dirname(abspath(__file__))) to get the parent directory of the python script and os.chdir into it to make the script run in the directory where it is located.
First of all, I am aware of the os.chdir() function and unfortunately it's not what I need.
I have a Python script that does stuff, including creating a folder new_folder. I am running this script from a terminal (it is added to the PATH)
C:\users\me\Desktop> my_script
and I want it to change the current working directory of my terminal, like this:
C:\users\me\Desktop> my_script
C:\users\me\Desktop\new_folder>
Is this even possible? And if so, how can I do it?
As stated in my comment, this is a very roundabout hacky way of doing it, and is probably a bad solution to your issue. that said, this is how it could be done:
if you use a batch file that calls a python script, that script would output the directory you wish to cd into:
example python script:
print("c:\your\directory")
example batch script:
for /f "delims=" %%i in ('C:\Path\To\python\python.exe your_python_script.py') do cd "%%i"
running this batch script yields:
c:\dir1>batchscript.bat
c:\dir1>for /f "delims=" %i in ('C:\Path\To\python\python.exe your_python_script.py') do cd "%i"
c:\dir1>cd "c:\dir2"
c:\dir2>
Notice we moved from dir1 to dir2 which is what I put in the output of my python script.
This will only work if your python script doesn't output anything other than the directory.
Again: not a good solution, but a solution.
I have been trying to use the output of a system command to use it as a part of the command in the next portion. However, I cannot seem to join it up properly and hence not being able to run the second command properly. The OS used is KALI LINUX and python 2.7
#IMPORTS
import commands, os, subprocess
os.system('mkdir -p ~/Desktop/TOOLS')
checkdir = commands.getoutput('ls ~/Desktop')
if 'TOOLS' in checkdir:
currentwd = subprocess.check_output('pwd', shell=True)
cmd = 'cp -R {}/RAW ~/Desktop/TOOLS/'.format(currentwd)
os.system(cmd)
os.system('cd ~/Desktop/TOOLS')
os.system('pwd')
The errors are:
cp: missing destination file operand after ‘/media/root/ARSENAL’
Try 'cp --help' for more information.
sh: 2: /RAW: not found
/media/root/ARSENAL
It seems that the reading of the first command is alright but it can't join with the RAW portion. I have read many other solutions, but they seem to be for shell scripting instead.
Assuming you haven't called os.chdir() anywhere prior to the cp -R, then you can use a relative path. Changing the code to...
if 'TOOLS' in checkdir:
cmd = 'cp -R RAW ~/Desktop/TOOLS'
os.system(cmd)
...should do the trick.
Note that the line...
os.system('cd ~/Desktop/TOOLS')
...will not do what you expect. os.system() spawns a subshell, so it will just change the working directory for that process and then exit. The calling process's working directory will remain unchanged.
If you want to change the working directory for the calling process, use...
os.chdir(os.path.expanduser('~/Desktop/TOOLS'))
However, Python has all this functionality built-in, so you can do it without spawning any subshells...
import os, shutil
# Specify your path constants once only, so it's easier to change
# them later
SOURCE_PATH = 'RAW'
DEST_PATH = os.path.expanduser('~/Desktop/TOOLS/RAW')
# Recursively copy the files, creating the destination path if necessary.
shutil.copytree(SOURCE_PATH, DEST_PATH)
# Change to the new directory
os.chdir(DEST_PATH)
# Print the current working directory
print os.getcwd()
I have a simple bash script that allows cron to execute a series of Python scripts in a virtualenv. The script keeps raising No such file or directory errors.
~/nightly.sh works fine:
#!/bin/bash
source virt_env/myproject/bin/activate
cd virt_env/myproject/main
python script1.py
python script2.py
I want to keep everything in ~/virt_env/myproject/main/ to simplify deployment. I thought I could call bash virt_env/myproject/main/nightly.sh on this:
#!/bin/bash
MAINDIR=`dirname $0`
cd $MAINDIR
source ../bin/activate
python script1.py
python script2.py
but I get the No such file or directory. If I manually cd to ~/virt_env/myproject/main/, then I can run the main commands no problem. Clearly I'm missing something about how dirname and cd work in this context.
How can I point bash at the right place?
Solution
As proposed in the accepted answer, it's best to avoid calling cd from within the script and use an explicit path variable instead. Here's the working version of virt_env/myproject/main/nightly.sh:
#!/bin/bash
MAINDIR=`dirname $0`
echo "The main directory is" $MAINDIR
# Activate virtual environment
source $MAINDIR/../bin/activate
# Run Python scripts
python $MAINDIR/python1.py
python $MAINDIR/python2.py
Because the Python scripts are now called from an arbitrary path, I needed to update the python scripts to be smarter about path awareness as well.
This code fails because os.path.basename omits path information:
# works when called with "python python1.py"
# fails when called with "python $MAINDIR/python1.py"
CONFIG_FILE = os.path.basename(__file__)[:-3] + ".config"
f = open(CONFIG_FILE,"r")
Updating it to use os.path.abspath fixes the problem:
# works regardless of how it is called
CONFIG_FILE = os.path.abspath(__file__)[:-3] + ".config"
f = open(CONFIG_FILE,"r")
Perhaps it would simply be better to eliminate the 'cd' command. Invoke everything from a full path specification. In your example add $MAINDIR/ to the executables.
Your bash script can then be in any directory where the executables are reachable. You are not exposed to the problems of what happens when cd fails.
Example:
cd yourdir
rm -f yourglob # oops things got removed from where you started if yourdir did not exist.
Two things:
Are you sure you know what the dirname command is doing? It's going to remove the top-level directory as well as the leading slash on whatever you call it on. I would make absolutely sure that the output of dirname is exactly what you think it is.
For example, /home/user/ will output /home.
You're using ~, which references the $HOME variable in your environment. You didn't mention where the cron is listed, but make sure it's not being run as a different user. Root's ~ and your ~ will be two completely different directories.
That's all I can think of. I hope that helps!
Add echo $MAINDIR after
MAINDIR=`dirname $0`
cd $MAINDIR
So you can see, if the contents of MAINDIR is correct.
Also you can run sh with -x or add set -x to the beginning of the script to see what happens.
I have a python script that looks files up in a relative directory. For example: the python script is in /home/username/projectname/. I have a file that is being called within the python script that is in /home/username/projectname/subfolder.
If I run the script from the shell as python scriptname.py it runs perfectly fine.
However, i'm trying to run the script as a startup service. I'm setting it up in webmin, and I believe its using a terminal command to call it. In the startup command, I'm doing something like this to call the script:
execute python home/username/projectname/scriptname.py. The script is starting up fine, but I get an error because it cant access the files in the relative directory.
I am guessing that there is a better way to call the python program from within the startup command so that its aware of the relative path.
import os
os.chdir("/tmp")
Also have:
os.getcwd()
Maybe you need the following instead?
import os.path
dir = os.path.dirname(__file__)
The process that starts your python script (probably forkink) has a pwd (its working directory). The idea is to change the pwd of the process before to fork and execute python.
You need to look over the manual of the process that executes the shell command, and see how to set the pwd.(in shell you use cd or pushd)
__file__ is the path that was used to run your script.
Copy this into a script file and try running it:
import os
print "This script was run as: %r" % __file__
print "This script is: %r" % os.path.abspath(__file__)
script_dir = os.path.dirname(os.path.abspath(__file__))
print "This script is in directory: %r" % script_dir
print "When started, the current directory was: %r" % os.getcwd()
os.chdir(script_dir)
print "After calling os.chdir(), the current directory is: %r" % os.getcwd()