পাইথনে আমি কীভাবে ওয়ার্কিং ডিরেক্টরি পরিবর্তন করব?


695

cd ওয়ার্কিং ডিরেক্টরি পরিবর্তন করার জন্য শেল কমান্ড।

পাইথনে আমি কীভাবে বর্তমান চলমান ডিরেক্টরিটি পরিবর্তন করব?


2
সুতরাং দোভাষী os.chdir(os.path.join(os.path.abspath(os.path.curdir),u'subfolder'))- বা?
মিস্টার_আর_আমস_ডি

উত্তর:


764

আপনি এর সাথে ওয়ার্কিং ডিরেক্টরিটি পরিবর্তন করতে পারেন:

import os

os.chdir(path)

এই পদ্ধতিটি ব্যবহার করার সময় দুটি সেরা অনুশীলন অনুসরণ করতে হবে:

  1. অবৈধ পথে ব্যতিক্রম (উইন্ডোজআরার, ওএসআরআর) ধরুন। যদি ব্যতিক্রম ছুঁড়ে দেওয়া হয় তবে কোনও পুনরাবৃত্ত ক্রিয়াকলাপ করবেন না, বিশেষত ধ্বংসাত্মক ones তারা পুরানো পথে পরিচালনা করবে, নতুন নয়।
  2. আপনার কাজ শেষ হয়ে গেলে আপনার পুরানো ডিরেক্টরিতে ফিরে যান। এটি ব্রায়ান এম হান্ট তার উত্তরে যেমন করেছেন, তেমন একটি প্রসঙ্গ পরিচালককে আপনার চিডির কলটি মোড়ক করে একটি ব্যতিক্রম-নিরাপদ উপায়ে করা যেতে পারে ।

সাব প্রোসেসে বর্তমান ওয়ার্কিং ডিরেক্টরি পরিবর্তন করা প্যারেন্ট প্রসেসের বর্তমান ওয়ার্কিং ডিরেক্টরিটি পরিবর্তন করে না। পাইথন ইন্টারপ্রেটারের ক্ষেত্রেও এটি সত্য। আপনি os.chdir()কলিং প্রক্রিয়াটির CWD পরিবর্তন করতে ব্যবহার করতে পারবেন না ।


3
cdunn2001 এর লাইটওয়েট ডেকোরেটর-ভিত্তিক উত্তর হ'ল আধুনিক পাইথনের জন্য আদর্শ পন্থা। উপরের উত্তরটি কেন তা প্রমাণ করে। প্রসঙ্গ পরিচালকের বাইরে কখনও কল করবেনos.chdir() না , যদি না আপনি ভাবছেন যে আপনি কী করছেন। ( আপনি সম্ভবত তা করেন না
সিসিল কারি

6
আমি মনে করি এটি একটি ইন্টারেক্টিভ শেলের সবচেয়ে সহজ উপায়। নোট করুন যে উইন্ডোজটিতে আপনাকে ফরোয়ার্ড স্ল্যাশগুলি ব্যবহার করতে হবে, যেমনos.chdir("C:/path/to/location")
জোশিয়ার

একটি বিষয় সম্পর্কে সচেতন হওয়ার বিষয়টি হ'ল আপনি যদি অজগর প্রোগ্রামটিকে একটি এক্সিকিউটেবল বানান এবং ক্রোনটিতে চালান তবে এটি আপনার হোম ডিরেক্টরিতে শুরু হবে। সুতরাং সম্পূর্ণরূপে যোগ্য পথ ব্যবহার করা ভাল। এটি অবশ্যই কার্যকরভাবে কাজ করে, তবুও আমি পাইথন থেকে যে কোনও স্ক্রিপ্টে আবেদন করতে পারি সে ক্ষেত্রে আমি এখনও পুরোপুরিভাবে যোগ্য পন্থাগুলি ব্যবহার করি কারণ পাইথন প্রোগ্রামের বাইরেও এটি প্রয়োগ হওয়ার কোনও গ্যারান্টি নেই।
এসডসোলার

310

ওয়ার্কিং ডিরেক্টরি পরিবর্তন করার জন্য এখানে একটি প্রসঙ্গ পরিচালকের উদাহরণ। এটি অন্যত্র উল্লিখিত একটি অ্যাক্টিস্টেট সংস্করণের চেয়ে সহজ , তবে এটি কাজটি করে gets

প্রসঙ্গ পরিচালক: 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)

অথবা কনটেক্সট ম্যানেজার ব্যবহার করে আরও সংক্ষিপ্ত সমতুল্য (নীচে) চেষ্টা করুন ।

উদাহরণ

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.

আপনি কখন থেকে ডিরেক্টরিটি FROM পরিবর্তন করেছেন তা জানতে যদি আপনার প্রয়োজন হয় তবে আপনি কেবল return selfএর শেষে যুক্ত করতে পারেন __enter__। এইভাবে আপনি with cd('foo') as cm:আগের দিরটি করতে এবং অ্যাক্সেস করতে পারেনcm.savedPath
স্যাম এফ

মনে রাখবেন যে কেসগুলি রয়েছে, যেখানে পুরানো ডিরেক্টরিতে ফিরে আসা ("সংরক্ষিতপথে" সঞ্চিত একটি) সম্ভব নয়। উদাহরণস্বরূপ, যদি আরও প্রাইভেলজড প্রক্রিয়াটি কম প্রাইভেলজড প্রক্রিয়া চালায় তবে দ্বিতীয় প্রক্রিয়াটি প্রথম প্রক্রিয়াগুলি ওয়ার্কিং ডিরেক্টরি হিসাবে উত্তরাধিকার সূত্রে প্রাপ্ত হয়, এমনকি সেই ক্ষেত্রেও যেখানে দ্বিতীয় প্রক্রিয়া তার নিজস্ব ক্ষমতা নিয়ে সেই ডিরেক্টরিটিতে প্রবেশ করতে পারে না।
কাই পেটজকে

140

আমি এটি ব্যবহার করব os.chdir:

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

যাইহোক, আপনার যদি আপনার বর্তমান পথটি বের করার দরকার হয় তবে ব্যবহার করুন os.getcwd()

আরও এখানে


117

cd() একটি জেনারেটর এবং একটি সজ্জা ব্যবহার করে লিখতে সহজ।

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)

তারপরে, একটি ব্যতিক্রম ছুঁড়ে দেওয়ার পরেও ডিরেক্টরিটি উল্টানো হয়:

os.chdir('/home')

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

3
এছাড়াও, এই সম্ভাব্য ত্রুটিটি লক্ষ করুন (এটি ভুলে যেতে try/finally)।
cdunn2001

5
প্রতিভা! যদি স্বীকৃত উত্তর থেকে সূচনা মন্তব্যটি এই উত্তরে ইনজেক্ট করা হয় , তবে এটি হবে আদর্শহীন। তবুও, এই উত্তরের সংক্ষিপ্ত, পাইথোনিকালি নিরাপদ বাস্তবায়ন আমাকে যে সমস্ত অগ্রগতি দিতে হবে তা পরোয়ানা দেয়।
সিসিল কারি

3
কেন yieldএবং না return? এটি কি জেনারেটর হওয়ার কথা?
ইকনস

ফলন বনাম রিটার্নের প্রাসঙ্গিকতার বিষয়ে মন্তব্য করুন!
নিকো বেরোগোরি

1
@ নিকো বেরোগুরি, এটি জেনারেটর। প্রসঙ্গ লিবিকনটেক্সট ম্যানেজারে ডক্স দেখুন । এটি পাইথনের একটি খুব দরকারী প্যাটার্ন, শেখার জন্য মূল্যবান।
cdunn2001

25

Python- র একটি অপেক্ষাকৃত নতুন সংস্করণ ব্যবহার করছেন, তাহলে আপনি একটি প্রসঙ্গ ম্যানেজার, যেমন ব্যবহার করতে পারেন এই এক :

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

হালনাগাদ

আপনি যদি নিজের নিজস্ব রোল করতে পছন্দ করেন:

import os
from contextlib import contextmanager

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

1
ভাল সাধারণ ধারণা। অন্যান্য নির্ভরতা ছাড়াই এখানে একটি অ্যাক্টিস্টেট রেসিপি
সিএফআই

4
নির্ভরতা খারাপ। পাইথনের বিল্ট-ইন contextlib.contextmanagerডেকরেটার ভাল। দেখুন cdunn2001 এর প্রসাধক ভিত্তিক উত্তর , যা আদর্শভাবে এখন গৃহীত উত্তর হতে হবে।
সিসিল কারি

14

অন্যদের দ্বারা ইতিমধ্যে নির্দেশিত হিসাবে, উপরের সমস্ত সমাধান কেবলমাত্র বর্তমান প্রক্রিয়াটির কার্যকরী ডিরেক্টরিকে পরিবর্তন করে। আপনি ইউনিক্স শেল থেকে বেরিয়ে গেলে এটি হারিয়ে যায়। মরিয়া হলে আপনি এই ভয়ঙ্কর হ্যাকের সাহায্যে ইউনিক্সের প্যারেন্ট শেল ডিরেক্টরিটি পরিবর্তন করতে পারেন :

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

4
উন্মাদ, ভঙ্গুর হ্যাক বাধ্যতামূলক upvotes পায়। কারও কখনও এটি করা উচিত নয়, বিশেষত এটির সাথে "এবং ব্যবহারকারী যখন এটি চালনার সময় টাইপ করে ..." ক্যাভ্যাট। তবুও, এটি আমার মধ্যে বিদ্রোহী ঘাড়ের শিরোনামকে শিরোনাম করে দেখেছে যে পিতামাতা সিডাব্লুডি পরিবর্তন করা বাছাই করা কিন্তু আসলেই সম্ভব নয়। Upvotes! সবার জন্য উক্তি!
সিসিল কারি



8
import os

abs_path = 'C://a/b/c'
rel_path = './folder'

os.chdir(abs_path)
os.chdir(rel_path)

আপনি os.chdir (abs_path) বা os.chdir (rel_path) দিয়ে উভয়ই ব্যবহার করতে পারেন, আপেক্ষিক পথ ব্যবহার করার জন্য os.getcwd () কল করার দরকার নেই।


ভাল কাজ করে. ডিরেক্টরি পরিবর্তন করার আগে এবং পরে উভয়ই বর্তমান ডিরেক্টরিটি যাচাই করতে os.getcwd () ব্যবহার করতে পারেন ..
vinsinraw


3

আপনি যদি "সিডি .." বিকল্পের মতো কিছু করতে চান তবে কেবল টাইপ করুন:

os.chdir ( "..")

এটি উইন্ডোজের মতোই সিএমডি: সিডি .. অবশ্যই আমদানি করা ওএসটি প্রয়োজনীয় (যেমন আপনার কোডের প্রথম লাইন হিসাবে এটি টাইপ করুন)


0

আপনি যদি স্পাইডার ব্যবহার করেন এবং জিইউআই পছন্দ করেন, আপনি কেবল আপনার স্ক্রিনের উপরের ডানদিকে কোণার ফোল্ডার বোতামে ক্লিক করতে পারেন এবং বর্তমান ডিরেক্টরি হিসাবে যে ফোল্ডার / ডিরেক্টরিগুলি চান তা সন্ধান করতে পারেন। এটি করার পরে আপনি স্পাইডার আইডিইতে উইন্ডোটির ফাইল এক্সপ্লোরার ট্যাবে যেতে পারেন এবং সেখানে উপস্থিত সমস্ত ফাইল / ফোল্ডার দেখতে পাবেন। আপনার বর্তমান ওয়ার্কিং ডিরেক্টরিটি পরীক্ষা করতে স্পাইডার আইডিইয়ের কনসোলে যান এবং কেবল টাইপ করুন

pwd

এটি আপনি আগে যেমন নির্বাচন করেছেন ঠিক একই পথে মুদ্রণ করবে।


-1

স্ক্রিপ্ট প্রক্রিয়াটির বর্তমান ডিরেক্টরি পরিবর্তন করা তুচ্ছ। আমি মনে করি প্রশ্নটি আসলে কীভাবে কমান্ড উইন্ডোটির বর্তমান ডিরেক্টরিটি পরিবর্তন করতে হবে যা থেকে পাইথন স্ক্রিপ্টটি আহ্বান করা হয়েছে, যা খুব কঠিন। উইন্ডোজের ব্যাট স্ক্রিপ্ট বা ব্যাশ শেলের একটি বাশ স্ক্রিপ্ট একটি সাধারণ সিডি কমান্ড দিয়ে এটি করতে পারে কারণ শেলটি নিজেই ইন্টারপ্রেটার। উইন্ডোজ এবং লিনাক্স উভয়ই পাইথন একটি প্রোগ্রাম এবং কোনও প্রোগ্রামই সরাসরি তার পিতামাতার পরিবেশ পরিবর্তন করতে পারে না। তবে পাইথন স্ক্রিপ্টের সাথে একটি সাধারণ শেল স্ক্রিপ্টের সংমিশ্রণ বেশিরভাগ হার্ড স্টাফ করে যা পছন্দসই ফলাফল অর্জন করতে পারে। উদাহরণস্বরূপ, পশ্চাদপদ / ফরোয়ার্ড / পুনর্বিবেচনার জন্য ট্র্যাভারসাল ইতিহাস সহ একটি বর্ধিত সিডি কমান্ড তৈরি করতে, আমি একটি সহজ ব্যাট স্ক্রিপ্ট দ্বারা আহবান করা একটি অপেক্ষাকৃত জটিল পাইথন স্ক্রিপ্ট লিখেছিলাম। ট্র্যাভারসাল তালিকা একটি ফাইলে সংরক্ষণ করা হয়, প্রথম লাইনে লক্ষ্য ডিরেক্টরি সহ। যখন পাইথন স্ক্রিপ্টটি ফিরে আসে, ব্যাট স্ক্রিপ্ট ফাইলটির প্রথম লাইনটি পড়ে এবং এটি সিডির পক্ষে যুক্তি তোলে। সম্পূর্ণ ব্যাটের স্ক্রিপ্ট (ব্রেভিটির জন্য বিয়োগ মন্তব্য):

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

পাইথন স্ক্রিপ্ট, dSup.py হ'ল:

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)

যদিও এটি একটি দুর্দান্ত উত্তর, ওপি একটি উত্তর নির্বাচন করেছে যা বলে যে এটি পিতামাতার প্রক্রিয়ার CWD পরিবর্তন করার বিষয়ে নয়। এটি প্রশ্নের অর্থ কী তা সম্পর্কে কোনও সম্ভাব্য বিভ্রান্তি পরিষ্কার করে দেয়।
টিন ম্যান

টিন ম্যানের কাছে - আমি আমার পরামর্শ পোস্ট করার আগেই উত্তরটি নির্বাচন করা হয়েছিল। আমি মনে করি যে বিস্তৃত উত্তরগুলি বিভ্রান্তিকর হতে পারে। প্রদত্ত প্রক্রিয়াটির মধ্যে সিডি (অর্থাত একটি পাইথন স্ক্রিপ্ট) এত সহজ যে কেউ কেন এটি জিজ্ঞাসা করবে আমি জানি না।
ডেভিড ম্যাকক্র্যাকেন

1
আসলে সেই উত্তরটি বছর কয়েক আগে নির্বাচিত হয়েছিল । যদি এটি যথাযথ না হয় তবে এটির পরে অনেকবার ডেকে আনা হত।
টিন ম্যান

আমি মনে করি যে বিভ্রান্তি রয়ে গেছে। সাম্প্রতিককালে, "পাইথনটিতে লিনাক্সের" সিডি "কমান্ডটি সিমুলেট করা, এবং প্রোগ্রামটি প্রস্থান হওয়ার পরে ডিরেক্টরি পরিবর্তনটি অব্যাহত রাখে [সদৃশ]" এখানে উত্তর দেওয়া হয়েছে বলে খারিজ করা হলেও বাস্তবে, এই প্রশ্নটি নির্বাচিত উত্তরের দ্বারা সমাধান করা হয়নি। আমার পরামর্শ উইন্ডোজের জন্য তবে সমস্যাগুলি লিনাক্সে একই।
ডেভিড ম্যাকক্র্যাকেন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.