equivalent van Shell ‘CD’ -opdracht om de werkdirectory te wijzigen?

cdIs de Shell-opdracht om de werkdirectory te wijzigen.

Hoe verander ik de huidige werkdirectory in Python?


Antwoord 1, Autoriteit 100%

U kunt de werkmap wijzigen met:

import os
os.chdir(path)

Er zijn twee beste praktijken die moeten volgen bij het gebruik van deze methode:

  1. Vang de uitzondering (WindowsError, OSERROR) op ongeldig pad. Als de uitzondering wordt gegooid, voert u geen recursieve bewerkingen uit, met name destructieve. Ze zullen opereren op het oude pad en niet de nieuwe.
  2. Terug naar uw oude map wanneer u klaar bent. Dit kan op een uitzonderlijke veilige manier worden gedaan door je CHDIR-oproep in een contextmanager in te wikkelen, zoals Brian M. Hunt deed in Zijn antwoord .

De huidige werkdirectory in een subproces wijzigen, verandert de huidige werkdirectory in het ouderproces niet. Dit geldt ook voor de Python-tolk. U kunt os.chdir()niet gebruiken om de CWD van het oproepproces te wijzigen.


Antwoord 2, Autoriteit 39%

Hier is een voorbeeld van een contextbeheerder om de werkdirectory te wijzigen. Het is eenvoudiger dan een Activestate-versie verwezen naar elders, maar dit krijgt de werk gedaan.

Context Manager: cd

import os
class cd:
    """Context manager for changing the current working directory"""
    def __init__(self, newPath):
        self.newPath = os.path.expanduser(newPath)
    def __enter__(self):
        self.savedPath = os.getcwd()
        os.chdir(self.newPath)
    def __exit__(self, etype, value, traceback):
        os.chdir(self.savedPath)

Of probeer het meer beknopte equivalent(hieronder), met behulp van ContextManager.

Voorbeeld

import subprocess # just to call an arbitrary command e.g. 'ls'
# enter the directory like this:
with cd("~/Library"):
   # we are in ~/Library
   subprocess.call("ls")
# outside the context manager we are back wherever we started.

Antwoord 3, autoriteit 17%

Ik zou os.chdirals volgt gebruiken:

os.chdir("/path/to/change/to")

Trouwens, als je je huidige pad moet bepalen, gebruik dan os.getcwd().

Meer hier


Antwoord 4, autoriteit 16%

cd()is gemakkelijk te schrijven met behulp van een generator en een decorateur.

from contextlib import contextmanager
import os
@contextmanager
def cd(newdir):
    prevdir = os.getcwd()
    os.chdir(os.path.expanduser(newdir))
    try:
        yield
    finally:
        os.chdir(prevdir)

Vervolgens wordt de map teruggezet, zelfs nadat er een uitzondering is gegenereerd:

os.chdir('/home')
with cd('/tmp'):
    # ...
    raise Exception("There's no place like /home.")
# Directory is now back to '/home'.

Antwoord 5, autoriteit 3%

Als je een relatief nieuwe versie van Python gebruikt, kun je ook een contextmanager gebruiken, zoals deze:

from __future__ import with_statement
from grizzled.os import working_directory
with working_directory(path_to_directory):
    # code in here occurs within the directory
# code here is in the original directory

UPDATE

Als je liever je eigen rolt:

import os
from contextlib import contextmanager
@contextmanager
def working_directory(directory):
    owd = os.getcwd()
    try:
        os.chdir(directory)
        yield directory
    finally:
        os.chdir(owd)

Antwoord 6, autoriteit 2%

Zoals al door anderen is opgemerkt, veranderen alle bovenstaande oplossingen alleen de werkdirectory van het huidige proces. Dit gaat verloren wanneer u terugkeert naar de Unix-shell. Als je wanhopig bent, kun je kuntde bovenliggende shell-directory op Unix wijzigen met deze vreselijke hack:

def quote_against_shell_expansion(s):
    import pipes
    return pipes.quote(s)
def put_text_back_into_terminal_input_buffer(text):
    # use of this means that it only works in an interactive session
    # (and if the user types while it runs they could insert characters between the characters in 'text'!)
    import fcntl, termios
    for c in text:
        fcntl.ioctl(1, termios.TIOCSTI, c)
def change_parent_process_directory(dest):
    # the horror
    put_text_back_into_terminal_input_buffer("cd "+quote_against_shell_expansion(dest)+"\n")

Antwoord 7

os.chdir()is de juiste manier.


Antwoord 8

os.chdir()is de Pythonic-versie van cd.


Antwoord 9

import os
abs_path = 'C://a/b/c'
rel_path = './folder'
os.chdir(abs_path)
os.chdir(rel_path)

Je kunt beide gebruiken met os.chdir(abs_path) of os.chdir(rel_path), het is niet nodig om os.getcwd() aan te roepen om een relatief pad te gebruiken.


Antwoord 10

Verder in de richting aangegeven door Brian en gebaseerd op sh(1.0.8+)

from sh import cd, ls
cd('/tmp')
print ls()

Antwoord 11

Als u iets als de “cd..”-optie wilt uitvoeren, typt u gewoon:

os.chdir(“..”)

het is hetzelfde als in Windows cmd: cd..
Natuurlijk is import osnodig (typ het bijvoorbeeld als 1e regel van je code)


Antwoord 12

De Path-objecten in de bibliotheek pathbieden zowel een contextmanager als een chdirmethode voor dit doel:

from path import Path
with Path("somewhere"):
    ...
Path("somewhere").chdir()

Antwoord 13

Als je spyder en love GUI gebruikt, kun je eenvoudig op de mapknop in de rechterbovenhoek van je scherm klikken en door de mappen/mappen navigeren die je als huidige map wilt hebben.
Nadat je dit hebt gedaan, kun je naar het tabblad Bestandsverkenner van het venster in spyder IDE gaan en je kunt alle bestanden/mappen zien die daar aanwezig zijn.
om uw huidige werkmap te controleren
ga naar de console van spyder IDE en typ gewoon

pwd

het zal hetzelfde pad afdrukken als dat je eerder hebt geselecteerd.


Antwoord 14

Het wijzigen van de huidige directory van het scriptproces is triviaal. Ik denk dat de vraag eigenlijk is hoe je de huidige map van het opdrachtvenster kunt wijzigen van waaruit een python-script wordt aangeroepen, wat erg moeilijk is. Een Bat-script in Windows of een Bash-script in een Bash-shell kan dit doen met een gewoon cd-commando omdat de shell zelf de interpreter is. In zowel Windows als Linux is Python een programma en geen enkel programma kan de omgeving van zijn bovenliggende direct veranderen. De combinatie van een eenvoudig shellscript met een Python-script dat de meeste moeilijke dingen doet, kan echter het gewenste resultaat bereiken. Om bijvoorbeeld een uitgebreide cd-opdracht te maken met traversal-geschiedenis voor achteruit/vooruit/selecteer opnieuw bezoeken, schreef ik een relatief complex Python-script dat werd aangeroepen door een eenvoudig bat-script. De doorlooplijst wordt opgeslagen in een bestand, met de doelmap op de eerste regel. Wanneer het python-script terugkeert, leest het bat-script de eerste regel van het bestand en maakt het het argument voor cd. Het volledige bat-script (minus opmerkingen voor de beknoptheid) is:

if _%1 == _. goto cdDone
if _%1 == _? goto help
if /i _%1 NEQ _-H goto doCd
:help
echo d.bat and dSup.py 2016.03.05. Extended chdir.
echo -C = clear traversal list.
echo -B or nothing = backward (to previous dir).
echo -F or - = forward (to next dir).
echo -R = remove current from list and return to previous.
echo -S = select from list.
echo -H, -h, ? = help.
echo . = make window title current directory.
echo Anything else = target directory.
goto done
:doCd
%~dp0dSup.py %1
for /F %%d in ( %~dp0dSupList ) do (
    cd %%d
    if errorlevel 1 ( %~dp0dSup.py -R )
    goto cdDone
)
:cdDone
title %CD%
:done

Het python-script, dSup.py is:

import sys, os, msvcrt
def indexNoCase ( slist, s ) :
    for idx in range( len( slist )) :
        if slist[idx].upper() == s.upper() :
            return idx
    raise ValueError
# .........main process ...................
if len( sys.argv ) < 2 :
    cmd = 1 # No argument defaults to -B, the most common operation
elif sys.argv[1][0] == '-':
    if len(sys.argv[1]) == 1 :
        cmd = 2 # '-' alone defaults to -F, second most common operation.
    else :
        cmd = 'CBFRS'.find( sys.argv[1][1:2].upper())
else :
    cmd = -1
    dir = os.path.abspath( sys.argv[1] ) + '\n'
# cmd is -1 = path, 0 = C, 1 = B, 2 = F, 3 = R, 4 = S
fo = open( os.path.dirname( sys.argv[0] ) + '\\dSupList', mode = 'a+t' )
fo.seek( 0 )
dlist = fo.readlines( -1 )
if len( dlist ) == 0 :
    dlist.append( os.getcwd() + '\n' ) # Prime new directory list with current.
if cmd == 1 : # B: move backward, i.e. to previous
    target = dlist.pop(0)
    dlist.append( target )
elif cmd == 2 : # F: move forward, i.e. to next
    target = dlist.pop( len( dlist ) - 1 )
    dlist.insert( 0, target )
elif cmd == 3 : # R: remove current from list. This forces cd to previous, a
                # desireable side-effect
    dlist.pop( 0 )
elif cmd == 4 : # S: select from list
# The current directory (dlist[0]) is included essentially as ESC.
    for idx in range( len( dlist )) :
        print( '(' + str( idx ) + ')', dlist[ idx ][:-1])
    while True :
        inp = msvcrt.getche()
        if inp.isdigit() :
            inp = int( inp )
            if inp < len( dlist ) :
                print( '' ) # Print the newline we didn't get from getche.
                break
        print( ' is out of range' )
# Select 0 means the current directory and the list is not changed. Otherwise
# the selected directory is moved to the top of the list. This can be done by
# either rotating the whole list until the selection is at the head or pop it
# and insert it to 0. It isn't obvious which would be better for the user but
# since pop-insert is simpler, it is used.
    if inp > 0 :
        dlist.insert( 0, dlist.pop( inp ))
elif cmd == -1 : # -1: dir is the requested new directory.
# If it is already in the list then remove it before inserting it at the head.
# This takes care of both the common case of it having been recently visited
# and the less common case of user mistakenly requesting current, in which
# case it is already at the head. Deleting and putting it back is a trivial
# inefficiency.
    try:
        dlist.pop( indexNoCase( dlist, dir ))
    except ValueError :
        pass
    dlist = dlist[:9] # Control list length by removing older dirs (should be
                      # no more than one).
    dlist.insert( 0, dir ) 
fo.truncate( 0 )
if cmd != 0 : # C: clear the list
    fo.writelines( dlist )
fo.close()
exit(0)

Other episodes