1

This is basically a duplicate of Change the current directory from a Bash script, except that I'm on windows and want to be able to change my command line directory from a powershell script.

I'm actually running a python script from the powershell file, parsing the output directory from that python script, and then using that output as the dir to change to, so if there's a way to do this from within the python script instead of the powershell file extra points!

To be 100% clear, yes I know about "cd" and "os.chdir", and no that's not what I want - that only changes the current directory for the script or batch file, NOT the command line that you are running from!

Code follows (batch file was my first attempt, I want it to be PS1 script):

sw.bat - parent dir added to sys $PATH

@echo off
set _PY_CMD_="python C:\code\switch\switch.py %*"
for /f "tokens=*" %%f in ('%_PY_CMD_%') do (
    cd /d %%f
)

switch.py

import os
import argparse

LOCAL = r'C:\code\local'


def parse_args():
    parser = argparse.ArgumentParser(description='Workspace manager tool.')
    parser.add_argument('command', type=str, help='The command to execute, or workspace to switch to.')
    return parser.parse_args()

def execute_command(command):
    if command in ['l', 'local']:
        print(LOCAL)

def main():
    args = parse_args()
    execute_command(args.command)

if __name__ == '__main__':
    main()
Darkhydro
  • 1,992
  • 4
  • 24
  • 43
  • 3
    Please add the relevant code: [\[SO\]: How to create a Minimal, Complete, and Verifiable example (mcve)](https://stackoverflow.com/help/mcve). – CristiFati Jul 16 '19 at 17:27

4 Answers4

3

If I got your question right, a simplistic approach would involve using [SS64]: FOR /F.

script.py:

target_dir = r"C:\Program Files"

print(target_dir)

script.bat:

@echo off

set _PY_CMD="e:\Work\Dev\VEnvs\py_064_03.07.03_test0\Scripts\python.exe" script.py

for /f "tokens=*" %%f in ('%_PY_CMD%') do (
    pushd "%%f"
)

Output:

[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q057062514]> ver

Microsoft Windows [Version 10.0.18362.239]

[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q057062514]> script.bat

[cfati@CFATI-5510-0:C:\Program Files]>
[cfati@CFATI-5510-0:C:\Program Files]> popd

[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q057062514]>

Notes:

  • I used pushd (instead of cd) because simple popd would return to the original directory. The drawback is that one has to remember (the stack) how many times they called pushd in order to match the correspondent popds. If want to switch to cd, use it like: cd /d %%f

@EDIT0:

At the beginning, the question was for batch only, after that the PowerShell (PS) requirement (which can qualify as a different question) was added.
Anyway, here's a simple (dummy) script that does the trick (I am not a PS expert).

script.ps1:

$PyCmdOutput = & 'e:\Work\Dev\VEnvs\py_064_03.07.03_test0\Scripts\python.exe' 'script.py'

Set-Location $PyCmdOutput

Output:

PS E:\Work\Dev\StackOverflow\q057062514> .\script.ps1
PS C:\Program Files>
CristiFati
  • 38,250
  • 9
  • 50
  • 87
  • I'm confused how this is working for you - I use "if defined _target_dir pushd %_target_dir%" in my bat file and it does not change my directory. I've testing using echo instead and the directory IS different (and correct). I also tested your solution and had no change to my cmd line dir. I am passing in %* in both my tests. The program is "sw.bat" so after adding to my path I call it like "sw l", where the l param specifies C:/code/local. – Darkhydro Jul 16 '19 at 17:59
  • You saved the 2 pieces of code in 2 files (the only thing that yoy should edit is the path to *Python* executable) and ran them and they don't work? You definitely did something wrong. It works fine on my machine (I copy / paste)ed the output. You should start from here, and only after it works add complexity to the *.bat* file. Also you should post your attempts in the question. – CristiFati Jul 16 '19 at 18:05
  • You caught me, I left out an important detail. I am using PowerShell, not cmd line, and would like it to work from that as well. Both your example and my own code work in standard cmd line. If it can't work in both, I'd rather have it work in PowerShell. – Darkhydro Jul 16 '19 at 18:17
0

Try os.chdir in Python:

os.chdir(path)

    Change the current working directory to path. Availability: Unix, Windows.
J. Blackadar
  • 1,821
  • 1
  • 11
  • 18
  • As stated in the question, I know this exists and it does not work. I am trying to change the cmd line dir, not python's current working directory. – Darkhydro Jul 16 '19 at 18:01
  • Your original, unedited question mentioned `os.cwd` not `os.chdir`. This is why I suggested the function. – J. Blackadar Jul 16 '19 at 18:35
0

Here's what I would do if you want to do the directory changes purely in batch:

Create a home directory Var of the Batch file you are calling your Python from. SET homeDir=%cd%

Then use cd to go into the desired directory. Once the program is in the directory, create a new command prompt using start "Title here (optional)" cmd.exe

Finally, return to the home directory with cd "%homeDir%"

The script might look something like this:

@echo off
REM using cd with no arguments returns the current directory path

SET homeDir=%cd%
REM set home Directory

cd "%desiredDirectory%"
REM moved directory

start "thisIsAName" cmd.exe
REM created new "shell" if you will

cd "%homeDir%"
REM returned to home directory
pause
IoCalisto
  • 55
  • 12
  • 1
    Starting a new cmd instance each time creates a lot of issues (like saving history) that I'm not willing to deal with. This is for a workspaces management tool, to improve my workflow speed. Thanks though! – Darkhydro Jul 16 '19 at 17:49
0

With the help of CristiFati, I got this working in a batch file. That solution is posted in the question. After some more googling, I've translated the batch file solution to a Powershell Script solution, which is below:

$command = "& python C:\code\switch\switch.py $args"
Invoke-Expression $command | Tee-Object -Variable out | Out-Null
set-location $out

No changes required to the Python file. Note - this answer is provided for those who want to take in any number of arguments to the python script and suppress stdout when calling the python script.

Darkhydro
  • 1,992
  • 4
  • 24
  • 43