I have a number of TSV files in a directory, and I would like to append the file name as an extra column on every line.
For Example my data looks like the below.
BEFORE
FileName: snapper_User_list.txt
Username group
user1 admin
user2 users
FileName: marlin_User_list.txt
Username group
root admin
sql admin
My ideal state would to be have one text file that looks like the below.
AFTER
FileName: output.txt
user1 admin snapper
user 2 users snapper
root admin marlin
sql admin marlin
For now I need to complete this in MS Windows.
I have the below script working, although it still displays the full filename in my output.
Rem Rename the files by just using the name before the underscore.
for /f "tokens=1* delims=_" %%i in ( 'dir *.txt /b' ) do (
rename %%i_%%j %%i.txt
)
Rem Combine the files.
FOR %%I IN (*.txt) DO (
FOR /f "tokens=*" %%a IN (%%I) DO (
echo %%a%TAB%%%I>>combined.txt
)
)
It's pretty ugly code.
Thanks.
(updated - update to my code)
I am going to assume you are referring to an underscore that occurs in the file name.
#echo off
setlocal
::The following defines a TAB character that is not preserved on StackOverflow
set "TAB= "
for %%F in (*.txt) do call :processFile "%%F"
exit /b
:processFile
set "name=%~1"
set name=%name:_=&rem %
for /f "usebackq delims=" %%a in (%1) do echo %%a%TAB%%name%>>combined.txt
The magic command is set name=%name:_=&rem %. It works by injecting a REMark command into the statement. Assume the current name is part1_part2.txt. After the search and replace expansion, the full statement becomes set name=part1&rem part2.txt
EDIT - Improved answer
Looking at your edited question, I realize there is a better way. I should have thought of parsing the name using FOR /F :-) You were 90% there!
#echo off
setlocal
::The following defines a TAB character that is not preserved on StackOverflow
set "TAB= "
for %%F in (*.txt) do (
for /f "delims=_" %%I in ("%%F") do (
for /f "usebackq delims=" %%a in ("%%F") do echo %%a%TAB%%%I>>combined.txt
)
)
Related
I want to loop through a folder and let run an algorithm on each .tif file found. Unfortunately this does not work for files which have a space character in their name. As my path already contains folders with space, i put the variable which stores the path name in double-quotation marks.
FOR /F %%k IN ('DIR /B "%mypath_import%"*.tif') DO (
SET infile=%%k
SET outfile=!infile:.tif=_UTM.tif!
REM ... do something
This is my attempt so far but it won't work for the files which include a space as well.
You done need all that. You can use the normal for loop without having to use /f
#echo off
setlocal enabledelayedexpansion
set "mypath_import=C:\Some path"
for %%i in ("%mypath_import%*.tif") do (
set "infile=%%~i"
echo "!infile:.tif=UTM.tif!"
)
The above will however echo full path to and file name, if you want filename only with extension:
#echo off
setlocal enabledelayedexpansion
set "mypath_import=C:\Some path"
for %%i in ("%mypath_import%*.tif") do (
set "infile=%%~nxi"
echo "!infile:.tif=UTM.tif!"
)
or without the need to delayedexpansion
#echo off
set "mypath_import=C:\Some path"
for %%i in ("%mypath_import%*.tif") do echo %%~dpni_UTM%%~xi
and again if you require the name and extension only.
#echo off
set "mypath_import=C:\Some path"
for %%i in ("%mypath_import%*.tif") do echo %%~ni_UTM%%~xi
EDIT
As per comment from #Stephan, keep in mind if you are doing actual renames and you run the script more than once it will keep on appending _UTM each time. So you'll get filename_UTM_UTM.tif etc. So you can exclude files from the loop by including findstr
for /f "delims=" %%i in ('dir /b *.tif ^|findstr /eiv "_UTM.tif"') do echo %%~ni_UTM%%~xi
I have a folder containing many files named as such: JBMA_23456.docx, JMRI_21456.docx, CM_22554.docx, QUA_11224.docx. How do I create a sub-folder for each file bearing the same name as the file but without the .docx file extension? Additionally, I want to store the filename only as variables.
For example, I need to create a sub-folder named JBMA_23456 from the document
JBMA_23456.docx. Can anyone point me in teh right direction?
#echo off
for %%A in (*.docx) do if not exist "%%~nA" md "%%~nA"
This creates a folder with the same name as each .docx file.
View modifiers in for /? or in call /?. The n modifier is the name.
Path modifiers:
dpnx is drive, path, name and extension.
Here's an example batch file which attempts to perform the tasks as laid out in your question:
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Set "BaseDir=C:\Users\Compo\Desktop\test"
Set "FileExt=.docx"
For /F "Delims==" %%A In ('Set var[ 2^>Nul') Do Set "%%A="
Set "i=0"
For /F "Delims=" %%A In ('Where "%BaseDir%":*%FileExt% 2^>Nul') Do (Set /A i+=1
Call Set "var[%%i%%]=%%~nA"
If Exist "%%~dpA%%~nA\" (Echo Sub-Folder %%~nA already exists in %BaseDir%
) Else (Set /P "=Creating sub-folder %%~nA in %BaseDir%"<Nul
MD "%%~dpA%%~nA">Nul 2>&1 && (Echo= was successful) || Echo= failed))
Set var[ 2>Nul
Pause
In order to use it, you would first ensure that the directory holding your files, (excluding any trailing backslash), is placed between the = and " on line 4, and the single file extension, (including the leading period, .), similarly on line 5.
It is not entirely clear what you are asking for...
Anyway, here is the code i made
echo off
chcp 65001
cls
for /f "usebackq delims=." %%0 in (`dir /b "*.docx"`) do (
set filename=%%0
md %filename%
)
cmd /k
It creates a new folder for every file. Feel free to ask if this was not what you expected
I downloaded about 34000 books in .txt format from Project Gutenberg. Now I want to rename all of them by its content. For example every text file includes its "Title" and "Author's Name" so I want to rename all the text files on its "Title" and "Author's Name" by some commands.
I created a batch file. It runs but is not renaming the files. This is my code:
#echo off&setlocal
cd E:\Test
for /f "delims=" %%i in ('dir /a-d/b *.txt') do (
set "nname="
set "fname=%%~i"
for /f "usebackqskip=7delims=" %%f in ("%%~i") do if not defined nname
set "nname=%%f"
setlocal enabledelayedexpansion
set "nname=!nname:~0,40!"
echo rename "!fname!" "!nname!"
endlocal
)
You can use this as a base
#echo off
setlocal enableextensions disabledelayedexpansion
rem Change to source folder
pushd "e:\test" && (
rem Where the renamed files will be placed to avoid re-rename
if not exist renamed\ md renamed
rem For each input file
for %%f in (*.txt) do (
rem Retrieve the data from inside the file
set "author=" & set "title="
for /f "tokens=1,* delims=: " %%a in ('
findstr /b "Author: Title:" "%%~ff"
') do if not defined %%a set "%%a=%%b"
rem If the fields have been retrieved then do the rename
if defined author if defined title (
setlocal enabledelayedexpansion
for /f "delims=" %%a in ("!author! - !title!") do (
endlocal
echo move "%%~ff" "renamed\%%a%%~xf"
rem NOTE: operation is only echoed to console
rem if console output seems correct, then
rem remove the echo command
)
)
)
rem Done. Return to previous active directory
popd
)
Of course, filesystem has rules about what is allowed in a file name and, not knowing what kind of characters can be found, this code could and probably will fail to rename some files.
Your current script will just print the rename commands, not execute them. You should remove echo (after checking what it produces) in this line:
echo rename "!fname!" "!nname!"
Your script also has a few formatting issues. There should be spaces like this:
for /f "usebackq skip=7 delims=" %%f in ("%%~i") do
And there should be no newline just after:
if not defined nname
This information below is contained in a text file and formatted as such.
/var/www/xxx/html/videos/video_folder_1
/var/www/xxx/html/videos/video_folder_2
/var/www/xxx/html/videos/video_folder_3
/var/www/xxx/html/videos/video_folder_4
/var/www/xxx/html/videos/video_folder_5
/var/www/xxx/html/videos/video_folder_6
/var/www/xxx/html/videos/video_folder_7
I also have a variable called %file_name% in the batch file already defined.
So lets say that is it is %file_name% = V001-video_folder_6.mp4
As you can see there is some more extra information, V001- and .mp4.
I would like to use the var %file_name% to search the text file and return the entire line. In this case it would return /var/www/xxx/html/videos/video_folder_6 and then put this information in a new var, let us say, %folder_path%.
I think I would use findstr however I have been playing around and not getting the best results.
The problem with the methods that use findstr is that they are slow, because they require to execute findstr.exe (a ~30KB file) each time. A simpler/faster solution is to use just internal Batch commands with the aid of an array. If the number of names to process is large, the difference in time between the two methods may be marked.
#echo off
setlocal EnableDelayedExpansion
rem Load the lines from text file into an array with the last part as index:
for /F "delims=" %%a in (test.txt) do (
set "line=%%a"
for %%b in (!line:/^= !) do set "lastPart=%%b"
set "folder[!lastPart!]=%%a"
)
set "file_name=V001-video_folder_6.mp4"
rem Get the folder from file_name:
for /F "tokens=2 delims=-." %%a in ("%file_name%") do set "folder_path=!folder[%%a]!"
echo Folder path is: %folder_path%
Let us assume the posted lines are in file Test.txt in current working directory.
#echo off
set "file_name=V001-video_folder_6.mp4"
for /F "tokens=2 delims=-." %%A in ("%file_name%") do set "folder=%%A"
for /F "delims=" %%P in ('%SystemRoot%\System32\findstr.exe "/C:%folder%" Test.txt') do (
set "folder_path=%%P"
goto NextCommand
)
:NextCommand
echo Full folder path is: %folder_path%
Open a command prompt window, enter the command for /?, hit key RETURN or ENTER and read output help to understand this little code.
The command goto inside FOR loop results in an immediate exit from loop processing output of findstr.exe after first found line containing the folder path of interest.
Perhaps better in case of searched folder is not found in text file:
#echo off
set "file_name=V01-VIDEOS for school (Miss Patrick).mp4"
for /F "tokens=2 delims=-." %%A in ("%file_name%") do set "folder=%%A"
for /F "delims=" %%P in ('%SystemRoot%\System32\findstr.exe "/C:%folder%" Test.txt') do (
set "folder_path=%%P"
goto FoundFolder
)
echo "%folder%" not found in file Test.txt.
pause
goto :EOF
:FoundFolder
echo Full folder path is: "%folder_path%"
pause
This should work:
::file_name=V001-video_folder_6.mp4
::file containing folder paths is called paths.txt
for /f "tokens=2 delims=-." %%a in ("%file_name%") do set FN=%%a
for /f %%a in ('findstr /E /L "%FN%" "paths.txt"') do set folder_path=%%a
echo %folder_path%
Which does what you want in effectively two lines.
Firstly, there are a couple of similar questions on here to this (Rename file based on file Content batch file being the one I have tried to work an answer from - but I have no real clue what I'm doing), however I cannot find anything that meets my exact needs, and this is my first real foray into batch programming so the syntax is fairly new to me.
The question:
I have several hundred text files, with different names, where the header is formatted like so:
"Event Type : Full Histogram"
"Serial Number : xxxxxx"
"Version : V 10.60-8.17 "
"File Name : W133FA0Z.580H"
"Histogram Start Time : 12:39:08"
"Histogram Start Date : 2014-04-11"
I would like if possible to create a batch file to rename all the files in the folder to the format of:
StartDate StartTime
so for this example:
2014-04-11 12:39:08
My problems lie in the fact I'm not sure how to actually point it to where to find the string if it was for just one line (I've tried editing the answers in the question I posted above). And, futhermore, I have no idea how to add a second bit of code to find the StartTime string and then append that to the StartDate.
Thanks in advance,
Chris
Here is a very efficient method.
#echo off
pushd "pathToYourFolderContainingFilesToRename"
for /f "tokens=1,3 delims=:" %%A in (
'findstr /bc:^"\"Histogram Start Date :" *.txt'
) do for /f delims^=^"^ %%C in (
"%%B"
) do for /f tokens^=4-6^ delims^=^":^ %%D in (
'findstr /bc:^"\"Histogram Start Time :" "%%A"'
) do ren "%%A" "%%C %%D.%%E.%%F.txt"
popd
The 1st loop serves two purposes. It establishes file names that contain the start date string, as well as also returning the date string for each file.
The 2nd loop strips out spaces and quotes from the date string.
The 3rd loop parses out the start time from the file.
The 2nd and 3rd loops have very awkward syntax to enable including a quote in the list of delimiters. The 2nd loop sets DELIMS to a quote and a space. The 3rd set DELIMS to quote, colon, and a space.
Assuming you JUST have file formatted like in your description in the working directory :
#echo off&cls
setlocal EnableDelayedExpansion
for %%x in (*.txt) do (
set /a $sw=1
for /f "skip=4 tokens=2-4 delims=:" %%a in ('type "%%x"') do (
if !$sw! equ 1 set $Time=%%a-%%b-%%c
if !$sw! equ 2 (
set $Date=%%a
call:DoRen !$Time:~1,-1! !$Date:~1,-1! %%~nx%%~xx)
set /a $sw+=1
)
)
exit/b
:DoRen
echo ren "%3" "%2 %1"
If the output is OK you can remove the echo
The following will get the output you want, where the output will look like 2014-04-11 123908.
#echo off
set file=test.txt
for /f "delims=: tokens=2-4" %%a in ('find "Time" %file%') do set ftime=%%a%%b%%c
for /f "delims=: tokens=2" %%a in ('find "Date" %file%') do set fdate=%%a
echo %fdate:~1,-1% %ftime:~1,-1%
If all the files are in the same directory, then you can simply do this in a another for loop.
#echo off
setLocal enableDelayedExpansion
for /f %%f in ('dir C:\whatever\path\*.txt /B') do (
for /f "delims=: tokens=2-4" %%a in ('find "Time" %%a') do set ftime=%%a%%b%%c
for /f "delims=: tokens=2" %%a in ('find "Date" %%a') do set fdate=%%a
ren "%%~a" "!fdate:~1,-1! !ftime:~1,-1!.txt"
)
This will rename all text files in a specified directory the date and time in their contents. Note that this does not account for text files that do not have the date and time in their contents. You can (and probably should) add that as you see fit.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
DEL incorrectformat.log 2>nul
DEL alreadyprocessed.log 2>nul
SET "sourcedir=U:\sourcedir"
FOR /f "delims=" %%a IN ('dir /b /a-d "%sourcedir%\*.txt" ') DO (
SET keepprocessing=Y
SET "newname="
FOR /f "tokens=1-5delims=:" %%b IN (
'TYPE "%sourcedir%\%%a"^|findstr /n /r "$" ') DO IF DEFINED keepprocessing (
IF %%b==1 IF NOT "%%~c"=="Event Type " SET "keepprocessing="&>>incorrectformat.log ECHO %%a
IF %%b==5 SET newname=%%d%%e%%f
IF %%b==6 (
SET "keepprocessing="
SET "newname=%%d!newname!.txt"
SET "newname=!newname:"=!"
SET "newname=!newname:~1!"
IF "!newname!"=="%%a" (>>alreadyprocessed.log ECHO(%%a) ELSE (ECHO REN "%sourcedir%\%%a" "!newname!")
)
)
)
GOTO :EOF
Here's my version.
You'd need to set the value of sourcedir to your target directory.
A list of files not matching the specified format is produced as incorrectformat.log
A list of already-processed files is produced as alreadyprocessed.log
The required REN commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO REN to REN to actually rename the files.