wmic to get lastmodified data on a file across a network - batch-file

I am trying to get lastmodified data using a batch file across a network
the line of code I am using to get the info is
wmic datafile where name="%file:\=\\%" get lastmodified
This works fine on local files but I get a No Instance(s) Available error when I try to use that line on a network file such as \\networkshare\folder\file.txt.

datafile does not support UNC paths.
You have two options
Connect to the remote node and ask for the file, knowing the local path to the file in the remote system
set "file=e:\somewhere\file.txt"
wmic /node:serverName datafile where name="%file:\=\\%" get lastmodified
If you don't know the local paths in the remote system, it is necessary to map a drive letter to the network share to retrieve the needed information
Sample code
#echo off
setlocal enableextensions disabledelayedexpansion
rem Configure file
set "file=\\server\share\folder\file.txt"
rem Separate path and filename
for %%a in ("%file%") do ( set "filePath=%%~dpa" & set "fileName=%%~nxa" )
rem Change to target path and adapt file path if sucessful
pushd "%filePath%" && (for %%a in (.\) do set "filePath=%%~fa")||(set "filePath=")
rem If the current directory has changed, get file data and return to previous folder
if defined filePath (
wmic datafile where "name='%filePath:\=\\%%fileName%'" get LastModified
popd
)

Related

How can I improve a batch file with a conditional who copy a jpg file refferring to a specific extension and to a specific database?

I created a .bat file with the following code in order to copy a random file from a directory A-POOL FOLDER into a directory B-FOLDER (with a fixed file name video.mp4). So, in the directory A there is a pool of .mp4 file, and in the directory B there is the the file video.mp4 (same name, but different video every time I execute my batch-file).
That's a code who do this. It perfectly works.
#echo off
setlocal EnableDelayedExpansion
cd C:\Users\aless\Desktop\example\A-POOL
set n=0
for %%f in (*.*) do (
set /A n+=1
set "file[!n!]=%%f"
)
for /L %%i in (1,1,%time:~-1%) do set "dummy=!random!"
set /A "rand=(n*%random%)/32768+1"
copy "!file[%rand%]!" C:\Users\aless\Desktop\example\B-FOLDER\video.mp4
FOR %%G IN ("!file[%rand%]!") DO >"C:\Users\aless\Desktop\example\B-FOLDER\title.txt" ECHO %%~nG
Now the question (different from last time):
In the directory A-POOL I have a lot of .mp4 files. I changed manually the .mp4 extension of every file with a code who rappresent a food.
For example: Filename.pizza, Filename2.pizza, Filename.pasta, Filename200.pasta, Filename.cheeseburger etc...
I created another folder named "FOOD-DATABASE" (in C:\Users\aless\Desktop\FOOD-DATABASE) who contains a big database of images in .jpg extension of the foods. The file NAMES of the food database are equal to the file EXTENSIONS of the files contained in A-POOL folder
Content of FOOD DATABASE folder:
(pasta.jpg, pizza,jpg, cheeseburger.jpg... etc..).
So I need to add to the code a string/conditional who execute e command who say:
If the picked random File have the extension .pizza COPY pizza.jpg from C:\Users\aless\Desktop\FOOD-DATABASE into C:\Users\aless\Desktop\B-FOLDER\FOOD.JPG (fixed name file)
Actually I don't want to add this strings for every food type... in few word the code strings have to read the extension of the picked random file and copy from C:\Users\aless\Desktop\FOOD-DATABASE to C:\Users\aless\Desktop...B FOLDER\FOOD.JPG (fixed name file) the file with the same name to the extension of the random file.
It's a mess... I know ;) Thanks for your help!
As mentioned in the comments, we know that the extension of the one file is the name of another file. so these variable expansions are important:
%%~nG
%%~xG
The last for loop sets a variable %food% from expanded %%~xG which is the extension of the file and using a random example would be .pizza We just need to get rid of the . and you have pizza. We do this by %food:~1.
#echo off
setlocal EnableDelayedExpansion
pushd "%userprofile%\Desktop\example\A-POOL"
set n=0
for %%f in (*.*) do (
set /A n+=1
set "file[!n!]=%%f"
)
for /L %%i in (1,1,%time:~-1%) do set "dummy=!random!"
set /A "rand=(n*%random%)/32768+1"
copy "!file[%rand%]!" "..\B-FOLDER\video.mp4" /Y
for %%G IN ("!file[%rand%]!") DO (
echo %%~nG > "..\B-FOLDER\title.txt"
set "food=%%~xG"
)
copy "..\FOOD-DATABASE\%food:~1%.jpg" "..\B-FOLDER\food.jpg" /Y
popd
Notes!
I am using pushd instead of cd and using relative path, not full paths as we are working in the same folder structure.
I can make out that you are running this on your own profile, so I replaced C:\users\<username> with %userprofile% in the event someone else wants to run it from a similar folder, their <username> will be different.
popd at the bottom of the script simply changes back to the previous working directory you were in before the last pushd. it is not needed for this particular script, but adding it so you can learn about it compared to pushd
All of the items I modified has some good help topics, you can find help topics on cmd by simply running the command name with an appended /? for instance for /?, set /? etc.

How to read path from textfile?

I have a .txt file with multiple lines. Each line contain a path to a folder on my network drive/computer:
[NetworkDrive_PathToFolder1]
[Computer_PathToFolder1]
[NetworkDrive_PathToFolder2]
[Computer_PathToFolder2]
[NetworkDrive_PathToFolder3]
[Computer_PathToFolder3]
etc...
The idea is to have a .bat file that will read line 1 and 2 and copy files in folder [NetworkDrive_PathToFolder1] into folder [Computer_PathToFolder1], then read line 3 and 4 and copy files in folder [NetworkDrive_PathToFolder2] into folder [Computer_PathToFolder2], etc.
This will enable me to add/remove paths without need of altering the code.
I'm not sure how the .txt file should look like. Maybe it's better to use a xml file?
This is for a Windows 10 computer with a network drive connected.
When I start my computer I want to automatically update some specific files from my network drive to a local folder on my computer.
To map the network drive I'll prefer to use PUSHD and POPD instead of NET USE since I don't want the network drive to be permanently mapped.
Today I have a .txt file with paths to the folders in the network drive:
[NetworkDrive_PathToFolder1]
[NetworkDrive_PathToFolder2]
[NetworkDrive_PathToFolder3]
etc...
And the path to the folder where the files are copied to are in the .bat file.
But then everything is just copied into the same folder at my computer.
FOR /F %%i IN (C:\UpdateFilesFromNetworkPaths.txt) DO (
NET USE L: /delete
NET USE L: %%i
xcopy L:\*.txt C:\FilesFromNetwork\ /d /y
)
Result from this code:
Every .txt files that doesn't exist in the folder [C:\FilesFromNetwork] will be copied from the paths in the textfile [UpdateFilesFromNetworkPaths.txt].
If a file exist, copy the file if it's a newer version.
So based on your post, it looks like you're trying to copy files based on paths in a text file. All groups of two (1-2, 3-4, 5-6) contain source and destination paths. This problem can be solved by a simple for loop and a simple counter.
Assuming your text file (.txt) is formatted in my example bellow:
C:\PathToNetworkDriveFolder1
C:\PathToComputerFolder1
C:\PathToNetworkDriveFolder2
C:\PathToComputerFolder2
C:\PathToNetworkDriveFolder3
C:\PathToComputerFolder3
Bellow will be the solution script:
#ECHO OFF
#Setlocal EnableDelayedExpansion
Set "Count=1"
Rem | Read The Text File Line By Line
FOR /F "tokens=*" %%A in ('Type "list.txt"') DO (
Rem | Grabbed First Line
IF "!Count!"=="1" (
Rem | Add One To Count
Set /a "Count=!Count!+1"
Rem | Save Current Variable
Set "NetworkDrivePath=%%A"
Rem | Grabbed Second Line
) else (
Rem | Subtract One To Count
Set /a "Count=!Count!-1"
Rem | Save Current Variable
Set "ComputerDrivePath=%%A"
Rem | Copy Files
Echo "!NetworkDrivePath!" "!ComputerDrivePath!"
)
)
Goto :EOF
Keep in mind my example uses list.txt. Feel free to change that to your example or your usage. If you have multiple text files you want to use your can simply add another for loop at the beginning to search for all *.txt file names.
For all my scripts, I put in rem comments to help you follow along in what each process is doing. For help on any of the commands do the following in a new window:
set /?
for /?
if /?
ren /?
So on.

WMIC Batch File

I am trying to use a .bat to get system info with WMIC. I want to create a folder in C:\ with the name of the computer, then have a few .txt files made within the folder with the info on I am seeking. This is what I have so far:
start cmd
cd C:\
md C:\%computername%_Software_Baseline
wmic
/output:C:\%computername%_Software_Baseline\Installed_Software.txt product get name,version
This is where my first roadblock is. I get the message that the file name is invalid. The next few are the other .txt files I want to create in that folder as well (Once I can do the first I should be able to apply it to these as well).
/output:C:\%computername%_Software_Baseline\Computer_System_Information.txt computersystem get domain,manufacturer,model,name,totalphysicalmemory
/output:C:\%computername%_Software_Baseline\Disk_Drive_Information.txt diskdrive get model,size,manufacturer
/output:C:\%computername%_Software_Baseline\CPU_Information.txt cpu get architecture,currentclockspeed,description,extclock,l2chachesize,manufacturer,name
/output:C:\%computername%_Software_Baseline\BIOS_Information.txt BIOS get serial number,name,smbiosbiosversion,manufacturer
/output:C:\%computername%_Software_Baseline\OS_Information.txt OS get name,cdsversion,manufacturer,freephysicalmemory,buildnumber
I also want this to save everything to a folder on my network as well, but that can wait until I get the script going.
I can't understand why not to perform the task within current cmd instance omitting start cmd:
#ECHO OFF
SETLOCAL enableextensions
md "C:\%computername%_Software_Baseline"
wmic /output:"C:\%computername%_Software_Baseline\Installed_Software.txt" product get name,version
or using pushd - popd command pair:
#ECHO OFF
SETLOCAL enableextensions
md "C:\%computername%_Software_Baseline" 2>NUL
pushd "C:\%computername%_Software_Baseline"
wmic /output:"Installed_Software.txt" product get name,version
rem further wmic commands here
popd
PUSHD: Change the current directory/folder and store the previous folder/path for use by the POPD command.
POPD: Change directory back to the path/folder most recently stored by the PUSHD command.
When a UNC path is specified, PUSHD will create a temporary drive
map and will then use that new drive. The temporary drive letters are
allocated in reverse alphabetical order, so if Z: is free it will be
used first.
POPD will also remove any temporary drive maps created by PUSHD.

Timestamp Not Returned in Batch

I am trying to run a batch file to update some software if the exe file is timestamped before the most recent version. To do this, I am using a well known for loop.
When I do this:
set file=%AppData%\spark\spark.properties
for %%a in (%file%) do set olddate=%%~ta
echo %olddate%
A timestamp is returned.
When I run it like this:
set spark_exe=%ProgramFiles%\Spark\Spark.exe
for %%a in (%spark_exe%) do set olddate=%%~ta
echo %olddate%
A timestamp is not returned. (Nor for any other files in that folder)
If I run:
set spark_exe=%ProgramFiles%\Spark\Spark.exe
for %%a in (%spark_exe%) do set fqp=%%~fa
echo %fqp%
I get the fully qualified path.
So... I can use SOME expansion variables.. but not others... why?... how?... help?
Thanks :)
I tried the batch code below and it worked:
#echo off
if exist "%ProgramFiles%\Spark\Spark.exe" (
set "spark_exe=%ProgramFiles%\Spark\Spark.exe"
) else if exist "%ProgramFiles(x86)%\Spark\Spark.exe" (
set "spark_exe=%ProgramFiles(x86)%\Spark\Spark.exe"
) else (
echo Error: Could not find Spark.exe
pause
goto :EOF
)
for %%a in ("%spark_exe%") do echo %%~ta
set "spark_exe="
I replaced also %%~ta by %%~fa to get name of file with path instead of last modification date and it worked, too.
Then I used Process Monitor of Sysinternals and logged the file system accesses on Spark.exe.
I could see that cmd.exe makes two IRP_MN_QUERY_DIRECTORY requests of type FileBothDirectoryInformation to check if the file exists and get full name of the file on using in batch file %%~fa.
There are the same two IRP_MN_QUERY_DIRECTORY requests with %%~ta in batch file. But additionally there is also a IRP_MJ_QUERY_INFORMATION request which is different to IRP_MN_QUERY_DIRECTORY as it is done with a file handle.
Is it possible that Spark.exe is currently created by the compiler when the batch file is executed and therefore any access on file is denied for any other application like cmd.exe?
I suggest to use also Process Monitor of Sysinternals and define Path ends with Spark.exe as include filter. Then run your batch file. Look now in Process Monitor if you can see any access denied in the log.

Changing the path location of a file to the desired path

I want to replace the content paths defined into the file i.e logging.properties to the desired location path of the jboss7 location .
Basically i'm using installer where i have to browse my jboss7 folder and locate it to any desired location of the user . But in few files of jboss7 there are some hardcoded path defined like in given logging.properties file.
I need to change that hard coded path to the desired location path.
As of now i'm having repl.bat and file test.bat files in the same folder.
repl.bat helper file could be find in following link:-
http://www.dostips.com/forum/viewtopic.php?f=3&t=3855
I just copied the code and created repl.bat file.
test.bat file :-
#ECHO OFF
SETLOCAL
SET "folder="
FOR /r "C:\" %%a IN (tintin.txt) do IF EXIST "%%a" SET "folder=%%~dpa"&GOTO got1
FOR /r "D:\" %%a IN (tintin.txt) do IF EXIST "%%a" SET "folder=%%~dpa"&GOTO got1
:got1
echo "%folder%"
PAUSE
set "newpath=%folder%"
set "newpath=%newpath:\=\\%"
echo "%newpath%"
PAUSE
type "logging.properties" | repl "(Directory=).*(\\\\standalone\\\\)" "$1%newpath%$2">"logging.properties.tmp"
PAUSE
move "logging.properties.tmp" "logging.properties"
PAUSE
GOTO :EOF
PAUSE
Here in this test.bat file , i'm searching a file tintin.txt file and setting the path into a variable name as 'folder'. tintin.txt file is just inside the folder of jboss7.This is because of the possibilities of more than one jboss7 application server folder into the system.
Till now i have got the path i.e "C:\Users\Anuj\Desktop\jboss7\" and set into the variable 'folder'.
Now there is file named logging.properties into the folder location
C:\Users\Anuj\Desktop\jboss7\standalone\configuration
logging.properties :-
com.latilla.import.uploadDirectory=C:\\progra~2\\Latilla\\C4i\\jboss7\\ standalone\\uploads
com.latilla.import.maxFilesUploadNumber=10
com.latilla.export.templateFile=C:\\progra~2\\Latilla\\C4i\\jboss7\\standalone\\templates\\GDV_HDI_Format.xls
com.latilla.etl.pluginsRootDirectory=C:\\progra~2\\Latilla\\C4i\\jboss7\\standalone\\cloverETL\\plugins
com.latilla.etl.templatesDirectory=C:\\progra~2\\Latilla\\C4i\\jboss7\\standalone\\etl
com.latilla.db.user=postgres
com.latilla.db.pass=password
repl.bat helper file helps to replace the url path with the desired path i.e path set to variable name 'folder'.
I want to replace the C:\progra~2\Latilla\C4i\jboss7\ with the path set to variable name 'folder'.
Note :-
here in logging.properties file path contents is having different format of path i.e C:\
means double slash. \
Might be the script that i have tried test.bat is incorrect.
When i double click the test.bat file i got error.
Although I can't help you with fixing the issue you are getting while using the repl.bat file, I can suggest a different way of solving the initial problem of path replacement.
If the jboss7 string is guaranteed to be present in all the original paths in your configuration file(s), you could try the following approach:
#ECHO OFF
SETLOCAL DisableDelayedExpansion
FOR /F "delims=" %%A IN ('DIR /B /S C:\tintin.txt') DO (CD /D "%%~dpA" & CALL :got1)
FOR /F "delims=" %%A IN ('DIR /B /S D:\tintin.txt') DO (CD /D "%%~dpA" & CALL :got1)
GOTO :EOF
:got1
SET "propfile=%CD%\standalone\configuration\logging.properties"
IF NOT EXIST "%propfile%" GOTO :EOF
SET "tempfile=%TEMP%\logging.properties.tmp"
FIND /I /V "jboss7\\" >"%tempfile%"
>>"%tempfile%" (
FOR /F "tokens=1,* delims=" %%I IN ('FIND /I "jboss7\\"') DO (
SET "pathname=%%J"
SETLOCAL EnableDelayedExpansion
IF NOT "!pathname!" == "!pathname:*jboss7\\=!" (
SET "pathname=%__CD__:\=\\%!pathname:*jboss7\\=!"
)
ECHO %%I=!pathname!
ENDLOCAL
)
)
ECHO Old file "%propfile%":
TYPE "%propfile%"
ECHO =======================================
ECHO New file:
TYPE "%tempfile%"
PAUSE
:: uncomment the next line once you have verified the replacement works correctly
::MOVE "%tempfile%" "%propfile%"
Searching for the tintin.txt file has been changed slightly so as to possibly make the process faster. Instead of iterating over every directory and checking if it contains the file, the loops now read the output of DIR, which returns only actually existing entries.
Note that you could also use a FOR /R loop, as in your present code, with the same effect i.e. returning only existing paths, but the IN clause would need to contain a mask rather than a normal name, but that would have to be a mask that couldn't match anything else in your system than just tintin.txt. For instance, if you knew for certain that there could be no file called tintin.txt1 or tintin.txtx or anything else where tintin.txt is followed by exactly one character, you could use the following template instead:
FOR /R "C:\" %%A IN (tintin.txt?) DO (CD /D "%%~dpA" & CALL :got1)
and same for D:\. That would return only references to files actually existing and matching the mask.
Also, you can see that the loops do not jump (GOTO) to the got1 label but instead call the got1 subroutine. With that change, it is possible to process many application instances in one go. I don't know yours can be installed multiple times. If not, you'll probably want to change it back to GOTO.
The subroutine in my script is referencing the config file using its full path as specified in your description (...\standalone\configuration\logging.properties). For some reason, in your script the file is referenced simply by its name, even though there's no preceding CD or PUSHD command changing the current directory to the location of the file. I assumed you were trying to simplify your script and omitted that bit, whether intentionally or not. Otherwise I may have missed something in your explanation and/or script.
After verifying that the config file exists at the expected location, the replacement itself is done in this way:
All the non-path config lines are written to a temporary file with one go.
Every config line containing a path is processed in this way:
if it does not contain the jboss7\\ string, it is omitted;
otherwise the part of the path up to and including jboss7\\ is removed;
the current directory is inserted before the remaining part (after every \ is replaced with \\);
the new value is put back into the config line;
the update line is added to the same temporary file.
The old version is of the configuration file replaced with the new one.
Obviously, the script may change the order of lines in the processed file, but it is assumed that that doesn't matter.

Resources