user3834916
user3834916

Reputation: 143

Getting FilePaths to work correctly in Batch (writing to a text file)

I'm iterating through about 300 directories and trying to create a text file in each. All of my code works except for file creation and subsequent writing. Here's how I'm attempting the write to file: (I should note that this code is within a nested for loop using setlocal EnableDelayedExpansion)

if !q! == 0 (
    set myString=%%f
    set myString=!myString:~0,-12!\temporary.txt        
    echo !m! >> !myString!
)

where %%f is the path to another text file I'm doing an analysis on, so I have to shorten the path. The name of this text file is uniform across all directories. I have tried just using:

echo !myString!

which produces an example output of (correct file-path):

C:\mywork2\MAX\BOTH0\temporary.txt

However, when I run the complete code block above I receive:

The fimename, directory name, or volume label syntax is incorrect.

If I use:

if !q! == 0 (
    set myString=%%f    
    echo !m! >> !myString:~0,-12!\temporary.txt
)

The program runs without error, but a text file is never created. The text file IS created, however, if I manually type the path (not possible for iteration). What am I doing wrong?


Here is the directory layout: C:\mywork2\MAX\ (arbitrary_name) \ dataSet.txt || and C:\mywork2\Trees_Orig\ (phylogenetic trees).

Example data sets (from phylogenetic tree):

#NEXUS
begin taxa;
    dimensions ntax=5020;
    taxlabels
    Tachyglossus_aculeatus
    Zaglossus_bruijni
    Zaglossus_bartoni
    Ornithorhynchus_anatinus
    Anomalurus_derbianus
    Anomalurus_beecrofti
    Anomalurus_pelii
    Anomalurus_pusillus
    Microtus_townsendii     
    Peromyscus_californicus
    Odocoileus_hemionus
    Canis_latrans
    Canis_lupus
    Urocyon_cinereoargenteus
    Vulpes_vulpes
    Lynx_lynx
    Euchoreutes_naso
    Jaculus_blanfordi
    Jaculus_jaculus
    Jaculus_orientalis
    Stylodipus_andrewsi
    Stylodipus_sungorus
    Monodelphis_iheringi

Example data sets (from dataSet.txt):

Species 
Microtus_townsendii     
Peromyscus_californicus     
Odocoileus_hemionus     
Canis_latrans       
Canis_lupus     
Urocyon_cinereoargenteus        
Vulpes_vulpes       
Lynx_lynx       
Puma_concolor       
Gulo_gulo       
Mephitis_mephitis       

Variable names:

k: is used to simulate an array, by serving as the indexes to each species in dataSet.txt
f: is a dataSet.txt from C:\mywork2\MAX\*
i: represents the first tab delimited term of each dataSet.txt row (I've truncated this for you)
g: is a .tre phylogenetic tree (there's 2), but I have truncated it's length due to example
j: represents the first term of each row within the phylogenetic tree

q: serves as a boolean variable which is 1 when a species from the phylogenetic tree
   is also in the dataSet.txt file. Otherwise 0.
n: serves as a boolean variable to tell when the batch file is examining species from the
   phylogenetic tree and not meta data.

m: is the index of each species within the phylogenetic tree. These are written to a text file
   when q = 0. This is because I will be creating a Paup block within a .NEX file to remove all
   species within the phylogenetic tree not present in dataSet.txt.

myString: this variable is used to hold a truncated file path. I want each temporary.txt file to
          be in the same directory as its respective dataSet.txt file.

Edit: Here is my code -->

setlocal EnableDelayedExpansion
SET "TabChar=   "

for /r C:\mywork2\MAX\ %%f in (*) do (
    set k=0
    for /f "delims=%TabChar%" %%i in (%%f) do ( 
        if NOT %%i == Species (
            set /A k+=1
            set elem[!k!]=%%i
        )
    )

    for /r C:\mywork2\Trees_Orig\ %%g in (*) do (
        set m=0
        set n=0

        for /f %%j in (%%g) do (
            set q=0

            if !n! == 1 (
                set /A m+=1
                for /L %%i in (1,1,!k!) do (
                    if !elem[%%i]! == %%j (
                        set q=1
                    )
                )

                if !q! == 0 (
                    set myString=%%f    
                    echo !m! >> !myString:~0,-12!\temporary.txt
                )
            )

            if %%j == taxlabels (
                set n=1
            )

            if %%j == Monodelphis_iheringi (
                set n=0
            )

        )

        PAUSE
    )
)

PAUSE

Upvotes: 1

Views: 59

Answers (2)

JosefZ
JosefZ

Reputation: 30268

Some injections only:

  • Omit "delims=%TabChar%", as any of the following are always valid delimiters: Comma ,, Semicolon ;, Equals =, Space and Tab
  • Comparison with == is always textual; therefore omit all == surrounding spaces; for best end, surround compared strings with e.g. quotes as follows: if NOT "%%i"=="Species" ( ...
  • Instead of redirecting echo to a file downright, try echo !m! ^>^> !myString:~0,-12!\temporary.txt to see all command as is

Upvotes: 1

Magoo
Magoo

Reputation: 80211

There's sufficient of the Yuletide spirit left for me to respond.

n and q are being used as flags. Better named as purposeflag to remove requirement to refer to documentation. Whereas setting the flags to 1/0 and using delayedexpansion to access their dynamic values will work, a better scheme is to set them to nothing or something then use if defined flagvalue which works whether delayedexpansion is invoked or not.

m and k are counter values, better named as purposecounter then there's no need for documentation.

mystring is another meaningless variable name. Better named destinationdirectory to document the purpose. There's no point in setting this variable where you are doing it - it depends solely on %%f so setting it at the start of the for %%f block means that it will only be set once for each %%f not each time the inner loop is executed (on the data provided, once against 15 times.)

The value assigned to mystring also appears unstable - relying on the length of the filename in %%f. Since you're simply selecting drive and path, %%~dpf is a better choice.

If you surround the destination filename with quotes, the process creates the destination file as apparently expected but since this is another file in the same directory as is being scanned by %%f then the filename temporary.txt will appear in that directory and your process will attempt to use that file as as a datasource, attempting to create dirname\t\temporary.txt and this directory does not exist (the t comes from dirname\temporary.txt processed by the substring to position -12. Using %%~dpf would cure that problem (but not the scanning of files created by this process)

To skip the scanning of the temporary.txt files, you could either add if /i "%%~nxf" neq "temporary.txt" as a gate after the for ... %%f...do or use a dir/s/b scan of the required directory as a list to source %%f since the list would be fully generated before the processing takes place, so excludes files generated within the process.

The results I obtained from the supplied data were 1 2 3 4 5 6 7 8 17 18 19 20 21 22 23 but you've not posted expected results, so I've no idea whether that result is correct.

Upvotes: 2

Related Questions