Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • change directory automatically according the filepath of using dataset

    Dear Stata users,
    I want to write a program that allow me to change directory automatically according the filepath of the dataset that I loaded into Stata. I plan to do this in following steps: (1) get the filepath of the file which I am using, I can get it through c(filename); (2) subtract the name of dataset (eg: foo.dta) from string of c(filename), thus the string of "current directory" is left; (3) change directory to current directory using -cd- command.
    An example: filepath is "E:\Desktop\Stata Plus\spmap\us_label.dta", subtracting result will be "E:\Desktop\Stata Plus\spmap", and thus I can cd "E:\Desktop\Stata Plus\spmap". I appreciate all your helps. Thank you.
    Code:
    . use "E:\Desktop\Stata Plus\spmap\us_label.dta"
    
    . display c(filename)
    E:\Desktop\Stata Plus\spmap\us_label.dta
    Last edited by Chen Samulsion; 11 Nov 2018, 23:54.

  • #2
    I think you need a mini program like this (all functions documented in help strfun):

    Code:
    use `"`c(sysdir_base)'a/auto.dta"' , clear
    
    version 14
    * save full path to macro
    local fullpath `"`c(filename)'"'
    * switch backward slashes to forward slashes in full path, if any
    local fullpath : subinstr local fullpath "\" "/" , all
    * calculate position of last "/"
    local delimpos=ustrlen(`"`fullpath'"')-ustrpos(ustrreverse(`"`fullpath'"'),"/")+1
    * split string into directory (characters 1 to "/"-1) and basename (characters "/"+1 to last)
    local directory=usubstr(`"`fullpath'"',1,`delimpos'-1)
    local basename=usubstr(`"`fullpath'"',`delimpos'+1,.)
    
    * display result
    display as result in smcl `"{text}basename is {result:`basename'}, directory is {result:`directory'}"'
    
    * change directory
    cd `"`directory'"'
    This code will
    1. save the full path of the currently opened file to a local macro
    2. calculate the position of the rightmost directory separator (/)
    3. split the full path into directory (left part) and file name (right part)
    Kind regards
    Bela

    PS: In Mata, there is a function available for this purpose, but for your special usage scenario, using it is not necessarily shorter:
    Code:
    use `"`c(sysdir_base)'a/auto.dta"' , clear
    
    version 14
    
    * save full path to macro
    local fullpath `"`c(filename)'"'
    * switch backward slashes to forward slashes in full path, if any
    local fullpath : subinstr local fullpath "\" "/" , all
    * let Mata do the trick calculating the base name:
    mata : st_local("basename",pathbasename(`"`fullpath'"'))
    * remove "/basename" from full path
    local directory : subinstr local fullpath `"/`basename'"' "" , all
    
    * display result
    display as result in smcl `"{text}basename is {result:`basename'}, directory is {result:`directory'}"'
    
    * change directory
    cd `"`directory'"'
    Last edited by Daniel Bela; 12 Nov 2018, 01:37. Reason: typo

    Comment


    • #3
      Also see pathutil (SSC).

      Best
      Daniel

      Comment


      • #4
        Dear daniel klein, thank you very much! I want to write my program mainly in Stata13, and I find that there are no strlen ustrlen udstrlen macro extended functions. Fortunately, with -pathutil- command you introduced in #3, I can make things easily with the workaround. Below is what I wrote, however it still has flaws, becasue when options are not "desk", the program will first change directory to desk and then to current path (or dolca).
        Code:
        program desk
         syntax [,DESK DOLCA PATH]
         if "`desk'"=="" {
          cd C:\Users\chen\Desktop\
         }
         if "`desk'"=="desk" {
          cd C:\Users\chen\Desktop\
         }
         if "`dolca'"=="dolca" {
          cd C:\ado\lca\
         }
         if "`path'"=="path" {
          pathutil split "`c(filename)'"
          cd "`s(directory)'"
         }
        end
        Code:
        . desk
        C:\Users\chen\Desktop
        
        . desk, path
        C:\Users\chen\Desktop
        E:\Files\Stata Plus\spmap
        
        . desk, dolca
        C:\Users\chen\Desktop
        C:\ado\lca
        Last edited by Chen Samulsion; 12 Nov 2018, 02:50.

        Comment


        • #5
          Hi again,

          Originally posted by Chen Samulsion View Post
          [...] I want to write my program mainly in Stata13, and I find that there are no strlen ustrlen udstrlen macro extended functions. [...]
          because you did not mention such in your original post, I assumed you were using a more recent version of Stata, sorry.

          My proposed code also works in Stata 13 or older with minimal adjustments: All you have to do is replace the Unicode string functions (btw, not extended macro functions!) ustrlen, ustrpos and usubstr with their non-unicode equivalents (remove the "u" at the beginning):
          Code:
          use `"`c(sysdir_base)'a/auto.dta"' , clear
          
          version 13
          * save full path to macro
          local fullpath `"`c(filename)'"'
          * switch backward slashes to forward slashes in full path, if any
          local fullpath : subinstr local fullpath "\" "/" , all
          * calculate position of last "/"
          local delimpos=strlen(`"`fullpath'"')-strpos(strreverse(`"`fullpath'"'),"/")+1
          * split string into directory (characters 1 to "/"-1) and basename (characters "/"+1 to last)
          local directory=substr(`"`fullpath'"',1,`delimpos'-1)
          local basename=substr(`"`fullpath'"',`delimpos'+1,.)
          
          * display result
          display as result in smcl `"{text}basename is {result:`basename'}, directory is {result:`directory'}"'
          
          * change directory
          cd `"`directory'"'
          Be warned, though, that you will encounter problems in case of file names containing Unicode characters (as Stata versions prior to 14 do not support Unicode)

          Regards
          Bela

          Comment


          • #6
            Originally posted by Chen Samulsion View Post
            [Below is what I wrote, however it still has flaws, becasue when options are not "desk", the program will first change directory to desk and then to current
            path (or dolca).
            Well, you start with

            Code:
            if "`desk'"=="" {
            cd C:\Users\chen\Desktop\
            }
            if "`desk'"=="desk" {
            cd C:\Users\chen\Desktop\
            }
            end
            That code means that the program will change to the desktop when option desk is not specified (first case) but it will also change to the desktop when option desk is specified (second case). You probably meant to code something else but it is not clear to me what that is.

            Best
            Daniel

            Comment


            • #7
              Dear Daniel Bela, sorry I confused you with daniel klein who post in #3. Thank you very much again. Your codes is just what I want, the steps are clear and understandable. I had tried to identify the position of the last backslash ("") before opening this thread. I tried many ways, but failed to recognize that there is strreverse() function I can use, and that these string functions, strlen, strpos, strreverse can be used in a local. And I also didn't master the usage of subinstr in a local. Now your codes teach me all of these tricks, I greatly appreciate your kindness.
              And Dear daniel klein, thank you for introducing me -pathutil- command. What I want to do in the little program posted in #4 is changing directory to desktop as default, and when I type options such as dolca or path, the program will then changing directory to the appropriate path. Its problem is that every time I type the option (dolca or path), the program will first change directory to desk and then to current path (or dolca).
              Code:
              program desk
               syntax [,DOLCA PATH]
                cd C:\Users\chen\Desktop\
               if "`dolca'"=="dolca" {
                cd C:\ado\lca\
               }
               if "`path'"=="path" {
                pathutil split "`c(filename)'"
                cd "`s(directory)'"
               }
              end

              Comment


              • #8
                Originally posted by Chen Samulsion View Post
                What I want to do in the little program posted in #4 is changing directory to desktop as default, and when I type options such as dolca or path, the program will then changing directory to the appropriate path. Its problem is that every time I type the option (dolca or path), the program will first change directory to desk and then to current path (or dolca).
                Something like this?

                Code:
                program desk
                    version 13
                    syntax [ , DOLCA PATH ]
                    if      ("`dolca'`path'"=="") local dir C:/Users/chen/Desktop
                    else if ("`dolca'"=="dolca")  local dir C:/ado/lca
                    else if ("`path'"=="path") {
                        pathutil split "`c(filename)'"
                        local dir "`s(directory)'"
                    }
                    else assert 0 // internal error
                    cd `"`dir'"'
                end
                Best
                Daniel
                Last edited by daniel klein; 12 Nov 2018, 07:30. Reason: fixed typo pointed out by Chen below

                Comment


                • #9
                  Dear daniel klein, it is exactly what I want. Thank you so much for all your help!
                  A little typo, it's "dolca" in the fifth line, a Stata plugin for doing latent class analysis written by The Methodology Center, Penn State.

                  Comment


                  • #10
                    If the program is going to be used by different user accounts, you can also replace C:/Users/chen/Desktop with:

                    Code:
                    "`:env USERPROFILE'\Desktop"
                    For users having a more recent version of Stata, notice the function ustrrpos can replace the whole expression with strlen/strreverse/ustrpos (and it would probably be better to use ustrreverse instead of strreverse anyway, or you will have surprises with non-ascii characters).

                    Comment


                    • #11
                      Dear Jean-Claude Arbaut, thank you so much. In Stata, there are full of pleasant amazement. By the way, the recent versions of Stata (14 & 15) are more powerful now, but I still do work mainly in Stata13. The reason is somewhat conservative. All the time, what I generated in more recent version of Stata cannot be translated back into older version for sharing and the likes. See https://www.statalist.org/forums/for...extended-ascii
                      Originally posted by Svend Juul View Post
                      Stata 14 is a big step forward. But there is a problem with the switch to Unicode for languages that so far used extended ASCII for some characters (German, French, Spanish, Portuguese, Danish, Norwegian, Swedish, Icelandic, Polish, Turkish, etc.). With the improved saveold command, Stata 14 can generate a dataset which can be opened by Stata 11 to 13, but legibility is poor. This is described in the Unicode help. unicode translate lets you translate from extended ASCII to Unicode, but the reverse is not possible.

                      At least, this is how I understand the possibilities. The problem will arise when we cooperate with or teach persons who don't have Stata 14. Does anybody have a solution?

                      Actually, Stat/Transfer 13 does the trick; it can translate a Stata 14 dataset to Stata 13, including translation to extended ASCII. To my mind this means that it is hardly impossible to expand the capability of unicode translate or saveold to make some "reverse translation".

                      Comment

                      Working...
                      X