Change the current directory pwd, from the python script itself - python

How to change the current directory of the command window from which a python script is invoked
I am writing a python script, that it should change directory (cd) of the current shell, to a specific directory, based on the user input.
The problem is everytime this script ends, I am back again to the original path, without changing.
bash-4.2$ pwd
/home/<username>/scripts
bash-4.2$ ./enterFW.py -fw <fw>
/filer/syslog_ng/2019/<fw>/2019/01/28 #<--I print the new directory, and it should be correct
bash-4.2$ pwd
/home/<username>/scripts #<-however after the script ends, i am back again to the original path
bash-4.2$
I change directory, using subprocess.call(['cd', <new path>]), or os.chdir(<new path>)...all are the same.
Please check, and advise

The only way I can think of is actual workaround. Where you pick up the output of your
script in current shell. Otherwise eveything gets executed in subshell.
myprogram.py
import os
new_dir = "/home/cabox/workspace"
os.chdir(new_dir)
print os.getcwd()
In linux shell:
cabox#box-codeanywhere:~/workspace/cliRtStocks$ pwd
/home/cabox/workspace/cliRtStocks
cabox#box-codeanywhere:~/workspace/cliRtStocks$ a=`python myprogram.py`;cd $a
cabox#box-codeanywhere:~/workspace$ pwd
/home/cabox/workspace
cabox#box-codeanywhere:~/workspace$

Related

Run Python Script From Script Directory/Current Directory

[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.

Replicate ". ./bash.sh" shell command in python script [duplicate]

I want to implement a userland command that will take one of its arguments (path) and change the directory to that dir. After the program completion I would like the shell to be in that directory. So I want to implement cd command, but with external program.
Can it be done in a python script or I have to write bash wrapper?
Example:
tdi#bayes:/home/$>python cd.py tdi
tdi#bayes:/home/tdi$>
Others have pointed out that you can't change the working directory of a parent from a child.
But there is a way you can achieve your goal -- if you cd from a shell function, it can change the working dir. Add this to your ~/.bashrc:
go() {
cd "$(python /path/to/cd.py "$1")"
}
Your script should print the path to the directory that you want to change to. For example, this could be your cd.py:
#!/usr/bin/python
import sys, os.path
if sys.argv[1] == 'tdi': print(os.path.expanduser('~/long/tedious/path/to/tdi'))
elif sys.argv[1] == 'xyz': print(os.path.expanduser('~/long/tedious/path/to/xyz'))
Then you can do:
tdi#bayes:/home/$> go tdi
tdi#bayes:/home/tdi$> go tdi
That is not going to be possible.
Your script runs in a sub-shell spawned by the parent shell where the command was issued.
Any cding done in the sub-shell does not affect the parent shell.
cd is exclusively(?) implemented as a shell internal command, because any external program cannot change parent shell's CWD.
As codaddict writes, what happens in your sub-shell does not affect the parent shell. However, if your goal is to present the user with a shell in a different directory, you could always have Python use os.chdir to change the sub-shell's working directory and then launch a new shell from Python. This will not change the working directory of the original shell, but will leave the user with one in a different directory.
As explained by mrdiskodave
in Equivalent of shell 'cd' command to change the working directory?
there is a hack to achieve the desired behavior in pure Python.
I made some modifications to the answer from mrdiskodave to make it work in Python 3:
The pipes.quote() function has moved to shlex.quote().
To mitigate the issue of user input during execution, you can delete any previous user input with the backspace character "\x08".
So my adaption looks like the following:
import fcntl
import shlex
import termios
from pathlib import Path
def change_directory(path: Path):
quoted_path = shlex.quote(str(path))
# Remove up to 32 characters entered by the user.
backspace = "\x08" * 32
cmd = f"{backspace}cd {quoted_path}\n"
for c in cmd:
fcntl.ioctl(1, termios.TIOCSTI, c)
I shall try to show how to set a Bash terminal's working directory to whatever path a Python program wants in a fairly easy way.
Only Bash can set its working directory, so routines are needed for Python and Bash. The Python program has a routine defined as:
fob=open(somefile,"w")
fob.write(dd)
fob.close()
"Somefile" could for convenience be a RAM disk file. Bash "mount" would show tmpfs mounted somewhere like "/run/user/1000", so somefile might be "/run/user/1000/pythonwkdir". "dd" is the full directory path name desired.
The Bash file would look like:
#!/bin/bash
#pysync ---Command ". pysync" will set bash dir to what Python recorded
cd `cat /run/user/1000/pythonwkdr`

How to know path of calling shell directory and use it in my python executable

Basically, I want to call a python program from anywhere using shell so I added a shebang and copied it to /usr/local/bin with executable permission. The python program takes a command line argument which is the relative path of an input file.
I am stuck here, I have no idea what to do so that I can obtain the absolute path of the shell. I am assuming once I get the absolute path somehow, I can use sys.argv[1] to get the entered relative path of the file(which I will append to the absolute path of shell working directory) but please do correct me it won't work.
You can Print Working Directory via os.environ['PWD']. Content of your_script.py:
#!/usr/bin/python3.5
import os
print(os.environ['PWD'])
Usage:
sanyash#sanyash-ub16:/etc/nginx$ your_script.py
/etc/nginx
sanyash#sanyash-ub16:/etc/nginx$

How to use the previous command output to use as a part of another command: python

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()

How to execute command by python?

I want to give a directory from raw_input of user and have cd to that directory by python
I used that code but it doesn't work for me:
a=raw_input("Enter The Dir :")
import os
os.system("cd "+a)
but it doesn't change the current directory of the python program!
If you want to change the current directory of a python program you should call os.chdir:
>>> import os
>>> os.getcwd() # show current working directory (cwd)
'/home/username'
>>> os.chdir('Downloads')
>>> os.getcwd()
'/home/username/Downloads'
Running the cd command via os.system doesn't work because os.system executes the command-line passed as argument in a new shell. From the documentation:
Execute the command (a string) in a subshell. This is implemented by
calling the Standard C function system(), and has the same
limitations.
The cd command actually does work, the problem is that it changes the current directory of the newly created shell, not of the current running python process. Using os.system('cd ' + x) is the same as doing:
$$(cd Downloads) #execute in a subshell
$pwd
/home/username
While calling os.chdir is equivalent to:
$cd Downloads
$pwd
/home/username/Downloads
i.e. it actually changes the current working directory as you want.
Note that os.system should be avoided. Use the subprocess module instead. This is even mentioned in the documentation for os.system:
The subprocess module provides more powerful facilities for spawning
new processes and retrieving their results; using that module is
preferable to using this function. See the Replacing Older Functions
with the subprocess Module section in the subprocess documentation for
some helpful recipes.
The subprocess module gives you much more control over the execution of the commands.
In fact your current code has a huge security flaw. For example what if the user entered a directory called (WARNING: do not provide this path to the abovementioned program. It will wipe your home directory!):
~;rm -fr .
While using subprocess you can avoid to get it interpreted as a shell command. For example:
import subprocess
dir_name = raw_input('Insert directory: ')
subprocess.call(['ls', dirname])
when provided with the above path will simply try to list the contents of a directory called ~;rm -fr . (a valid UNIX path), which probably doesn't exist.
While:
import os
dir_name = raw_input('Insert directory: ')
os.system('ls ' + dir_name=)
Will first list the contents of ~ (aka, your home directory), and then it will wipe the home.

Categories