Update file in each subdirectory with a specific name - powershell

I have a batch-file which pulls a file from a url using powershell and then outputs/updates the file in a specific directory. But I have many of these directories, the only thing that changes about the path is numbers between \command\ and \setup\. How would I get it to put the file in every folder automatically?
Essentially I would like to output the downloaded text file in each of the install subdirectories of that path.
Also how could I make it happen silently?
#echo off
echo !!! PRESS ANY KEY TO CONTINUE AND UPDATE!!!
pause
powershell -Command "Invoke-WebRequest http://example.com/log/read.txt" -OutFile C:\Users\Administrator\AppData\Roaming\base\command\234235234\setup\install\read.txt 2>NUL >NUL
echo !!! DONE NOW !!!
echo !!! YOU CAN RE-OPEN NOW !!!

for /d /r "dirname" %%a in (*) do if /i "%%~nxa"=="install" echo %%a
may be useful to you.
Your requirement is unclear. Do you want to copy the file to the install subdirectories of ...\234235234\.. only, or of ...\*\... ?
Replace dirname with the name of the starting directory, be it ...\234235234\.. or C:\Users\Administrator\AppData\Roaming\base\command and the command I have shown will report all of the install directories contained under dirname. All you need then do is to change the echo to an appropriate copy command - see copy /? from the prompt. You can suppress copy's responses by appending >nul 2>nul (suppress messages and suppress error messages)
for /d /r with * as the list element will process a list of all subdirectories starting at the nominated directory. The if command selects only the leaf directories that match install in either case (/i)
Since
for /d /r ...
does nor detect hidden directories, another approach is
for /f "delims=" %%a in ('dir /s /b /ad "dirname" ') do if /i "%%~nxa"=="sub1" echo %%a
Which in this case should be
for /f "delims=" %%a in ('dir /s /b /ad "C:\Users\Administrator\AppData\Roaming\base\command" ') do if /i "%%~nxa"=="sub1" echo %%a
The dir command produces a list in /b basic (name-only) form, /s including subdirectories, /ad of directories only (names with the directory attribute set). This list is processed line-by-line by for /f without delimiters so the entire line (including spaces, if any) is assigned to %%a and displayed.

Related

How to set a variable in cmd which is a string from powershell command result?

I want to store the result of powershell command in cmd variable as String : powershell -com "(ls | select -Last 1).FullName". How to do this?
CMD does not have a straightforward way of assigning command output to a variable. If the command produces just a single line you could use a for loop
for /f "delims=" %a in ('some_command /to /run') do #set "var=%a"
However, if the command produces multiple lines that will capture only the last line. A better approach would be redirecting the output of the command to a file and then reading that file into a variable:
set "tempfile=C:\temp\out.txt"
>"%tempfile%" some_command /to /run
set /p var=<"%tempfile%"
del /q "%tempfile%"
If you literally need only the last file in a directory you don't need to run PowerShell, though. That much CMD can do by itself:
for /f "delims=" %f in ('dir /a-d /b') do #set "var=%~ff"
Beware that you need to double the % characters when running this from a batch file.
A FOR loop can provide the path to the file. If the default directory sorting order is not the result needed, specify additional command line switches on the DIR command.
FOR /F "delims=" %F IN ('DIR /B') DO (SET "THE_FILE=%~fF")
ECHO THE_FILE is "%THE_FILE%"
In a .bat file script, double the percent characters on FOR loop variables.
FOR /F "delims=" %%F IN ('DIR /B') DO (SET "THE_FILE=%%~fF")
ECHO THE_FILE is "%THE_FILE%"
The .bat file scripts can also run PowerShell scripts. It is best practice to not use aliases such as ls in scripts.
FOR /F "delims=" %%F IN ('powershell -NoLogo -NoProfile -Command ^
"(Get-ChildItem -File | Select-Object -Last 1).FullName"') DO (SET "THE_FILE=%%~fF")
ECHO THE_FILE is "%THE_FILE%"
The problem with cmd here is that I want to get the full paths for
FOLDERs NOT recursive... this dir /ad /b doesn't give full paths and
this dir /ad /b /s does it recursively... – stakowerflol 2 hours ago
That's not a problem, you can return the full file path without recursing.
If you are changing directory to the path you need to check then it's stored in %CD%
If you need the path to whee the Script itself is it's stored in %~dp0
If you want to provide an argument to specify and arbitrary path and get all of the listings it will be that argument term (EG %~1)
With all three possible options you can do the same thing:
Either
Prepend the provided variable to the output of the chosen directory enumeration method
OR
Use a For loop to get the file names at that path and show the result with the full path.
IE
Jenkins_A_Dir.bat
#(
SETLOCAL
ECHO OFF
SET "_Last="
ECHO.%~1 | FIND /I ":\" > NUL && (
SET "_CheckHere=%~1"
)
IF NOT DEFINED _CheckHere (
SET "_CheckHere=C:\Default\Path\When\No Argument\Specified"
)
)
REM Use a For loop to get everything in one variable
FOR %%A IN (
"%_CheckHere%\*"
) DO (
SET "_Last=%%A"
)
ECHO.Found "%_Last%"
REM Use `FOR /F` with DIR, and append the path to Check:
SET "_Last="
FOR /F "Tokens=*" %%A IN ('
DIR /A-D /B "%_CheckHere%\*"
') DO (
SET "_Last=%_CheckHere%\%%A"
)
ECHO.Found "%_Last%"
Of course you don't NEED to have set a variable such as _CheckHere
Instead, you can just replace all of the instances of %_CheckHere% with `%~1 instead, that would work just fine in the above examples too.
Okay, what if you just wanted to check the location the script was running in.
Then either change the above to use SET "_CheckHere=%~dp0" or Replace %_CheckHere% with %~dp0 throughout.
Okay but what if you don't want to set a variable you want to it to use the current working directory.
When then, even easier:
Jenkins_Current_Dir.bat
#(
SETLOCAL
ECHO OFF
SET "_Last="
)
REM Use a For loop to get everything in one variable
FOR %%A IN (
"*"
) DO (
SET "_Last=%%~fA"
)
ECHO.Found "%_Last%"
REM Use `FOR /F` with DIR, and let it append the current working directory to the path:
SET "_Last="
FOR /F "Tokens=*" %%A IN ('
DIR /A-D /B "*"
') DO (
SET "_Last=%%~fA"
)
ECHO.Found "%_Last%"

Batch File to display file name and then certain lines in the files

I have a folder of .log files where the content of each file has multiple lines of the following format:
yyyy/mm/dd, hh:mm:ss, ComputerName, IPAddress, stuff, stuff
I would like to create a batch file to parse through the .log files and create the following output for any line in a file where ComputerName starts with "XPLT":
filename,yyyy/mm/dd,ComputerName,IPAddress
And preferably, I'd like to only look at files with a modified date within the last 30 days.
So far, I've only gotten the following code which doesn't even work and doesn't even include the file modified date and parsing by ComputerName. Looking for help because I've just not done this very much, and I can't find a good example online.
Echo EID,Date,PCName,IPAdd>CitrixLogs.csv
setlocal enabledelayedexpansion
for /f "tokens=1,3,4" %%i in ('dir /b "C:\LogFiles\*.log"') do (
echo %%i,%%j,%%k,%%l>>CitrixLogs.csv
)
I'd use a bit of FINDSTR magic:
set LOG_DIR=c:\logfiles
for /f "tokens=1-7 delims=:," %%L in ('%SystemRoot%\System32\findstr.exe /r /c:"^[0-9][0-9][0-9][0-9]/[0-9][0-9]/[0-9][0-9],[0-9][0-9]:[0-9][0-9]:[0-9][0-9],xplt.*," %LOG_DIR%\*.log') do #echo %%L,%%M,%%N:%%O:%%P,%%Q,%%R,
`
REM
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
FOR /f "tokens=2-8delims=:, " %%a IN ('findstr /l /i /c:", XPLT" "%sourcedir%\*.log"') DO (
ECHO %%~nxa,%%b,%%c:%%d:%%e,%%f,%%g
)
GOTO :eof
redirect to your .csv as you will...
#echo off
setlocal enableextensions disabledelayedexpansion
:: configuration
set "logFolder=%cd%"
set "logFiles=*.log"
set "maxFileAge=30"
set "computerName=XPLT"
set "outputFile=CitrixLogs.csv"
:: adjust commands to execute according to configuration
set "ageFilter=robocopy "%logFolder%" "%logFolder%" "%logFiles%" /l /is /njh /njs /nc /ns /ndl /maxage:%maxFileAge%"
set "contentFilter=findstr /f:/ /i /r /c:"^^[^^,]*, [^^,]*, %computerName%" "
:: Generate output file
( echo(EID,Date,PCName,IPAdd
for /f "usebackq tokens=2,* delims=:" %%a in (
`cmd /q /c "for /f tokens^=* %%a in ('%ageFilter%') do echo(%%a" ^| %contentFilter% `
) do for /f "tokens=1,3,4 delims=," %%c in ("%%b") do echo(%%~nxa,%%c,%%d,%%e
) > "%outputFile%"
endlocal
This will use robocopy (or you can change it with forfiles) to search for files with a max age of 30 days in the indicated folder. Files will not be copied (/l) but the list will be echoed (the rest of the switch configure the output). This list of files is piped into findstr (/f:/) indicating where to search for the lines that match the indicated condition. This will generate an output with each line in the input file matching the condition, prefixed with the name (full name) of the file. This line is then splitted to output only the required fields.

Command Prompt "dir /b /s > file.txt" need to remove directories from results

I am using the following command to dump the complete file listings recursively from a directory.
dir /b /s c:\myfolder > c:\mylist.txt
This works fine but it is display the results with the full path as well, beacuse I am using a regex expression on the results I need them to display only the filenames.
Anyone any ideas?
Kind of an old question but if someone stumbles across this hoping for an answer, perhaps this will help them out.
Running this from the windows command line (CMD.exe) use:
setlocal enabledelayedexpansion
for /f "delims=" %a in ('dir /b /s c:\myfolder"') do (#echo %~nxa >>c:\mylist.txt)
endlocal
Running this from a windows .BAT script use:
setlocal enabledelayedexpansion
for /f "delims=" %%a in ('dir /b /s c:\myfolder"') do (#echo %%~nxa >>c:\mylist.txt)
endlocal
The output might look something like this depending on what files are in the folder you're running the code in:
file1.fil
file2.fil
file3.fil
UNDERSTANDING WHAT THE CODE IS DOING
for /f
means to run a loop through files in this case using the dir /b /s command to help get those files names from directories (folders) and subdirectories (subfolders). As stated in the question, this will give you complete paths to the files. So instead of file.txt you will get C:\folder\file.txt.
"delims="
in this case tells the for loop that it wants the variable %a or %%a
to only have 1 folderpath and filename for every loop.
%a (CMD.exe) %%a (.BAT)
as mentioned above is a variable that changes with each loop. so
everytime the command dir /b /s finds a new filename the variable
%%a changes to the filename.
example:
Loop 1: %%a = c:\folder\file1.fil
Loop 2: %%a = c:\folder\file2.fil
dir /b /s
is the command to print out the files of a directory (folder). By
using the /b and /s the questioner is adding additional criteria.
the command dir not only prints out the files and directories
(folders) in that directory (folder) but also some additional
information about the directory.
the /b tells the command dir that it doesn't want the additional
information.. just the filenames.
The /s tells the command dir to include all the files and
subdirectories (subfolders) in that folder.
do
is the part of the loop that tells what to do during that particular
loop. So in this case it is only doing this one command every loop
(#echo %%~nxa >>c:\mylist.txt)
#echo
is a simple command that prints out whatever you want either to your
computer screen or in this case to a txt file by using #echo %%~nxa
>>c:\mylist.txt
the >> before c:\mylist.txt is especially important. Every time a
loop happens it starts a new line in the txt file and writes the
variable to that line. If only one > is specified it will overwrite
the line in the txt file everytime the loop happens. Which will
defeat the purpose of what this script is designed to do.
%~nxa (CMD.exe) %%~nxa (.BAT)
is the variable %%a as mentioned above except it is parsed (edited)
out the way the questioner #fightstarr20 asked for. Instead of
printing out the variable as C:\myfolder\myfile.fil the variable
will print out as myfile.fil
the ~ in %%~nxa tells the program you want to modify the variable
%%a. In this case by adding n and x.
the n in %%~nxa tells the program you want to modify the variable %%a by
excluding the path from the variable.
example.
-variable %%a = C:\folder\filename.fil
-variable %%~na = filename.
-If you notice however that it leaves the extension .fil off of the filename.
the x in %%~nxa tells the program you want to modify the variable %%a
by excluding the path and the filename from the variable, so all you will get is the extension of the filename.
example.
-variable %%a = C:\folder\filename.fil
-variable %%~xa = .fil
so if you combine both of the modifiers n and x to the variable %%a
you will get the full filename including the extension.
example:
-variable %%a = c:\folder\filename.fil
-variable %%~nxa = filename.fil
setlocal enabledelayedexpansion
explained simply is a command that needs to be in the script before
the for loop in order to allow the variable %%a to be modified or "expanded".
endlocal
this turns off the setlocal enabledelayedexpansion command
To get a very helpful explanation and reference for CMD commands I recommend reading ss64.com and for a great forum to get CMD answers I'd recommend dostips.com
Change your regex to get the filename from the entire path.
If you can use powershell, look at Get-ChildItem. You can have more powerful options with it.
Use it like this
dir /b /s C:\myfolder>C:\temp.txt
echo exit>>C:\temp.txt
goto loop
:loop
set /p _x=<temp.txt
findstr /v /c:"%_x%" temp.txt>temp2.txt
type temp2.txt>temp.txt
set _x=%_x:*\=%
echo %_x%>file.txt
if "%_x%" == "exit" (
del temp.txt
del temp2.txt
exit
)
goto loop
You can use for instead of goto if you like, but it will be basicaly the same.
Sorry about the last one...
I know I'm a bit late, but it hurts me that nobody said to take away the /s
dir /b c:\myfolder > c:\mylist.txt
That should do it.
This would surely work, as it works for me.
dir D:(Path to files) /s /b >d:\filelist.txt
You can just use this code:
dir /b > A_fileslist.txt
Copy inside a notepad editor and save as "Fileslist.bat".

Batch File XCopy Command

I have a batch file which loops through a content of a text file and copies a specific file using xcopy command.
here's the snippet.
for /f %%a in (FilesToCopy.txt) do (
xcopy ..\..\Common\%%a Common\%%a /i /d /c /v /s /y /f
xcopy Common\%%a ..\..\Common\%%a /i /d /C /v /s /y /f
)
%%a contains values like
Images\image1.jpg
Images\image2.jpg
so when xcopy is executed it would look like
xcopy ..\..\Common\Images\image1.jpg Common\Images\image1.jpg /i /d /c /v /s /y
upon execute it would then prompt this message
Does Common\Images\image1.png specify a file name
or directory name on the target
(F = file, D = directory)?
it seems that the /i command doesn' work or i am missing something here to suppress the message above.
Well, you left out the second statement the help gives about /I:
/I If destination does not exist and copying more than one file,
assumes that destination must be a directory.
You are only ever copying one file at a time, so /I doesn't apply.
You can probably hack-solving this by piping F into the command and suppressing output:
echo F|xcopy ..\..\Common\%%a Common\%%a /i /d /c /v /s /y /f >nul
(Won't work on non-English versions of Windows; but probably that's the least of your problems, given that the batch already fails for file names with spaces :-))
You could try building a single long list of file names to copy:
setlocal enabledelayedexpansion enableextensions
set LIST=
for /f %%a in (FilesToCopy.txt) do set LIST=!LIST! "..\..\Common\%%a"
xcopy %LIST% Common /i /d /c /v /s /y /f
This requires two passes over the initial file, though. And it fails when the list of file names gets longer than 8190 characters.
The destination should be a path, then it won't ask:
xcopy ..\..\Common\Images\image1.jpg Common\Images\ /i /d /c /v /s /y
In your case, you can use path extraction with %~p on the destination since you may want to preserve that:
xcopy ..\..\Common\%%a Common\%%~pa /i /d /c /v /s /y

Appending a txt file from multiple CSVs in subdirectories

I am trying to write a batch file which will append all *.csv files in the immediate subdirectories to a single text file in the current directory.
From various sources I have managed to piece together this code which works fine for files in the current dir but not sub-dirs
for %%a in (*.csv) do (type %%a >> csvreport.txt)
If anybody could help me with this I would be extremely grateful as I have tried various approaches with wildcards but without success.
Yet another option...
for /f usebackq %%a in (`dir /s /b *.csv`) do (type %%a >> csvreport.txt)
EDIT: Reading your details a bit more ... you want just the immediate directories, you can do this:
for /f usebackq %%a in (`dir /b /ad`) do for %%b in ("%%a"\*.csv) do (type "%%b" >> csvreport.txt)
for /R .\ %%a in (*.csv) do (type %%a >> csvreport.txt)
The /R indicates recursive and the parameter afterward is the folder in which to start (.\ is the current directory).
You can find up more if you run for /?
dir /ad /b > dirs.txt
for /f "tokens=1*" %%i in (dirs.txt) do cd %%i & for %%b in (*.csv) do (type %%b >> c:\csvreport.txt) & cd ..
Using the /R flag will traverse all subdirectory trees. You can nest the 'for' statements to only work with the immediate subdirectories but not their subdirectories.