I've noticed when using DIR in windows command line for one particular case wildcards don't function as I'd expect. Example:
dir *.doc
runs similar to
dir *.doc*
I've only noticed this behavior when the wildcard directory precedes the period (which is an important and frequent case). Whats even stranger is if you run either:
dir *.d
dir *.do
It will execute as expected. It's only once you hit 3 character extensions the strange behavior starts. I mentioned it runs similar to the command above because if the contents after the *. is not the extension it will not return the file. E.g.:
dir *.tar
will not return file.tar.gz but will return file.targa
Why is this and how can it be avoided?
The DIR command matches against both long and short names.
Windows file names that do not meet the old 8.3 DOS standard are automatically given a short file name alias that does meet the standard. (This can be disabled on NTFS drives)
For example, a file with a name of "file.targa" is assigned a short name of "file~1.tar" on my local hard drive. The rules for the short name are undocumented, and the assigned name varies depending on what names already exist within the folder when the file is created. But one thing that is consistent is that long extensions are truncated to the first three characters of the long extension.
Given that DIR searches both long and short names, you can now see that "*.tar" matches "file~1.tar" which is the short name for "file.targa"
This issue exists for pretty much every command that performs uses wild card file masks, including FOR, COPY, MOVE, REN, etc.
Workarounds
If your volume is NTFS, then you (or your administrator) can disable short names. But existing short names persist, it only disables generation of short names for future files. This is not a very practical solution, since you may not be in a position to know if any short file names exist.
If you simply need a list of files, without the other DIR info, then you can pipe the result of DIR /B through FINDSTR to get the desired result.
dir /b *.tar | findstr /le ".tar"
The extension is the part after the last dot. Anything before the last dot is the filename, including dots as ordinary characters.
Also remember that dir matches short and long names.
Related
We are in the process of migrating files from one share to another. We have built a tool in which the user can select directories and/or individual files to be copied to a destination share. The tool generates an individual RoboCopy command for each of the files or directories in the collection that results from the selection made by the user.
We are having problems if an individual file to be copied starts with a dash, for instance:
robocopy c:\temp c:\temp2 -a.txt
RoboCopy bails out with: ERROR : Invalid Parameter #3 : "-a.txt"
We tried the usual suspects (quotes around the filename etc.), but so far nothing seems to work. Any idea how to get around this, without resorting to renaming the file prior to copying?
This appears to be a bug in robocopy; it has some other known similar ones:
https://support.microsoft.com/en-us/kb/2646454
Here's a possible workaround:
robocopy c:\temp c:\temp2 *-a.txt /xf *?-a.txt
*-a.txt will still match "-a.txt", but it also matches "x-a.txt", "xx-a.txt", etc.
The /xf file exclusion knocks out "x-a.txt", "xx-a.txt", and any other file with characters (specifically, at least one character) in front of the hyphen.
I've confirmed that the above command will match only "-a.txt" even if c:\temp also contains these files:
other folder\-a.txt
-a.txt1
-a1.txt
x-a.txt
xx-a.txt
I'm not 100% confident though, so you might want to think up some other filenames to test that against.
Basically, i would like to use the type command, but I can't provide the actual path.
Currently my attempt was
type "./TESTS/Test1.txt"
but I'm assuming that since it's a relative path, it can't work.
I've run into the same issue with copy and xcopy.
I have been unable to solve this issue or find anything online.
Is there way to do this?
EDIT:
To clarify, I am trying to get my .bat file, to read the contents of a .txt file located in a subfolder (meaning the subfolder and the .bat file are in the same folder), and print it to the console.
Since you've now edited your question but seemingly not provided feedback on my earlier comment, here it is as an answer.
Windows and it's command interpreter, cmd.exe uses the backslash \ as its path separator.
Although many commands seem to accept the forward slash interchangeably, Type isn't one of those.
Additionally .\ is relative only to the current working directory, and in cmd.exe is unnecessary, though valid.
The following should therefore work as you intended:
Type TESTS\Test1.txt
Type "TESTS\Test1.txt"
Type .\TESTS\Test1.txt
Type ".\TESTS\Test1.txt"
If the location you are using is being received in the batch file with the forward slashes, you could set it to a variable, then expand that variable substituting the forward slashes for backward slashes:
Set "Variable=./TESTS/Test1.txt"
Type "%Variable:/=\%"
It may be necessary, depending upon the code we cannot see, to navigate to the batch file directory first, since it may not necessarily be the current working directory at the time of the invokation of those commands.
To do that use:
CD /D "%~dp0"
%~dp0 provides the folder, where your batchfile resides (including the last \) (does of course only work inside a batch file). So:
type "%~dp0Test\test1.txt"
is exactly what you want: <folder_where_my_batchfile_is\><subfolder_Test>\<File_test1.txt>
independent of your "working folder" (where the batchfile might have cd or pushd to).
Wouldn't it basically work by using %CD%? Like, TYPE "%CD%/Subfolder/Test1.txt"? %CD% is the windows variable for "Current Directory" and should be set to whatever directory the batch file is working in and since you're trying to access a folder within the same directory this should work. You're question is quite unclear, however, and I hope I'm not misinterpreting.
I have an exe file. I want to run it several times repeatedly one after another. I tried below batch file but couldnt do it is there a way to do it? Sorry but i am a rookie in code writing
#echo off
start ran.exe
start ran.exe
start ran.exe
Assuming that ran.exe is in the current folder or on your path, then you simply write:
#echo off
ran
ran
ran
to invoke it three times. If it is not found on the PATH, then use a fully qualified name like this:
#echo off
c:\path\to\ran
c:\path\to\ran
c:\path\to\ran
Running a program is the normal effect of naming it on a line of a batch file.
Furthermore, because .EXE is listed in the PATHEXT environment variable, you don't need to include that in the name, unless there is also a file name ran.com since .COM is listed in the default value of PATHEXT ahead of .EXE.
The START builtin command is only needed in batch files for handling some special cases. See the output of START /?1 for its documentation. In general, you don't need it just to launch programs.
Update: To generalize this to N invocations, use the FOR command. FOR is extremely powerful, type FOR /? at the command prompt for documentation. For N repeats specified as the argument to the batch file, and passing the current count to the command as its first argument do this:
#echo off
for /L %%N in (1,1,%1) do c:\path\to\ran %%N
The tricky thing to remember with FOR is that the iteration variable must be named with two percent signs in batch files. The help text says that, but only in passing.
Update 2: Some more details and explanation.
In this case, we want to repeat a command N times. FOR supports a variety of kinds of loops, but the easiest way to get exactly N iterations is to use its /L option which uses a starting value, a step size, and an ending value to define the number of iterations.
These are specified in parenthesis, as FOR /L %%N (start,step,end). To get a simple counter of 1 to N, we tell it to start at 1, step by 1, and to stop at the value of the first argument to the batch file which is named %1.
The arguments to the batch file itself are named as %1 through %9, and %* names all of the arguments. Note that there is a vast minefield of subtlety here related to properly quoting file names that contain spaces. To keep life simple, try very hard not to need to do that. Otherwise, CALL /? documents the command line argument conventions, and SET /? documents many things related to general batch file variables.
Other forms of FOR let you iterate over files (no option), directories (/D), directories recursively in a tree (/R), or various parts of the contents of files (/F).
On a regular basis, I am trying to clean up some data folders for an ERP program prior to doing a backup and performing maintenance on the data tables. I've been using Windows Explorer to search for extraneous backup and temporary files prior to the full backup (the maintenance procedures create backup files during the process that aren't always removed), but I'd like to just run it all through a batch file to simplify and speed up the process. I'm filtering with the following:
*NGT????????????.old
*Wrk*????????????.m4t
Also, the command I'm using:
del /S /Q
Both of these work perfectly though the search function within Explorer. The first one works correctly in a command prompt, but the second doesn't. The series of ?s are created by the ERP software as a time stamp, to indicate a copy of the original was created at that time. And the second * represents a one or two character user ID that indicates the user that created the file (it isn't all that important except that the character length isn't always the same). When I try to filter in the command prompt with that second filter, not only does it grab the files I want it to, but it also grabs the original source files which DO NOT have a time stamp on them. For example, the following file names:
File 1) AR_AgedInvoiceReportWrk.M4T
File 2) AR_AgedInvoiceReportWrkTB081615903027.M4T
File 2 is the only one that should be deleted, but it will delete both File 1 and File 2. I've even tried using two or three ?s instead of the second * just to see if a difference would occur, but it doesn't.
Does the command prompt not recognize the ? the way Explorer does? What am I missing?
DIR and it seems other tools match the short file name and the long filename. Your short filenames have wrk as the leading characters and then you are matching a whole swag of any-character.
A solution is to use something like DIR /b /a-d and pipe it through findstr with a regexp, and that will match only the long filenames.
MY QUESTION:
I have the same situation as Rishi. I have a number of versions of the same song by the same artist that appear on different CD's. If I use the batch command as written, will DOS overwrite songs with the same name, even if the file size is different for each unique file?
PREVIOUS QUESTION: DOS command to move all files in subdirectories one level up
REFERENCE Rishi asked the question on Jan 15th:
"I have a folder with a lot of sub folders with one or more files in each. I am trying to write a batch file that moves all those files to C:\songs (for example).
C:>FOR /R C:\Test %i IN (*) DO MOVE %i C:\Songs
The folders Test and songs exist, but I get an error saying
%i was unexpected at this time.
What am I doing wrong?"
ANSWER WAS
"FOR /R %i IN (C:\Test*) DO MOVE "%i" C:\Songs
In a batch file, it has to be %%i. Weird quirk of batch."
Within a given folder there can only be one version of a file with a given name. When executed within a batch, the MOVE command will automatically overwrite any pre-existing file of the same name. So the answer to your question is - YES, a file with the same name will be over-written, even if it has a different file size. (Note - if you are using Windows XP then you are not using DOS)
You can prevent a batch move from overwriting an existing file by piping N to MOVE with the -y option:
echo n | move /-y "%%~i" "C:\songs\"
If you want to copy and preserve both versions into the same folder, then at least one version will have to be renamed. You will have to decide what kind of naming scheme you want to use before you can begin coming up with a solution.