Reputation: 653
I would like to sort a set of files in a specific order using a batch file.
The files should be grouped by Floor
number and sorted by a string which is contained in the filename.
An example of some file names are as follows:
Floor_1_SomeName_PCI_Some Trailing Text.JPG Floor_1_SomeName_RSRP_Some Trailing Text.JPG Floor_1_SomeName_RSRQ_Some Trailing Text.JPG Floor_1_SomeName_RSSI_Some Trailing Text.JPG Floor_1_SomeName_SINR_Some Trailing Text.JPG Floor_1_SomeName_TX Power_Some Trailing Text.JPG Floor_2_SomeName_PCI_Some Trailing Text.JPG Floor_2_SomeName_RSRP_Some Trailing Text.JPG Floor_2_SomeName_RSRQ_Some Trailing Text.JPG Floor_2_SomeName_RSSI_Some Trailing Text.JPG Floor_2_SomeName_SINR_Some Trailing Text.JPG Floor_2_SomeName_TX Power_Some Trailing Text.JPG
I would like to sort all files by its Floor
number first, then by the following order:
RSSI RSRP RSRQ SINR TX Power PCI
Is there a way I can utilize the sort
command to organize this?
Upvotes: 1
Views: 1398
Reputation: 34909
Here is another approach that uses a temporary file; this holds a list of matching file names, which is read multiple times, once per keyword RSSI
, RSRP
, RSRQ
, SINR
, TX Power
and PCI
(reading from a file is better than building the list of files in terms of performance). Here is the code:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_FILES=.\Floor_*_*_*_*.jpg" & rem // (location and pattern of files to be sorted)
rem // Create temporary file containing list of all matching file names:
> "%~dpn0.tmp" (
rem // Capture filtered list of files and split them into `_`-separated tokens:
for /F "tokens=1-4* delims=_" %%A in ('
dir /B /A:-D /O:N "%_FILES%" ^| ^(
rem/ Filter for files whose names match the given pattern: ^& ^
findstr /R /I /C:"^Floor_[0-9][0-9]*_[^_][^_]*_[A-Z ][A-Z ]*_[^_].*\.jpg$"
^)
') do (
rem // Pad floor number with leading zeroes:
set "NUM=0000%%B"
rem /* Store floor number prefix in variable named `$FLOOR_`, followed by
rem four-digit floor number, to get a list of unique floor numbers: */
call set "$FLOOR_%%NUM:~-4%%=%%A_%%B"
rem // Write original file name into temporary file:
echo(%%A_%%B_%%C_%%D_%%E
)
)
rem /* Loop over the unique floor numbers by retrieving a sorted list of all variables
rem whose names begin with `$FLOOR_`; the following zero-padded four-digit floor
rem number ensures ascending numerical sort order (sorted by `set` implicitly): */
for /F "tokens=1,* delims==" %%E in ('2^> nul set $FLOOR_') do (
rem /* Return file names from temporary file holding the currently iterated floor
rem number with the special keywords (fourth token) in the proposed order: */
findstr /R /I /C:"^%%F_[^_][^_]*_RSSI_" "%~dpn0.tmp"
findstr /R /I /C:"^%%F_[^_][^_]*_RSRP_" "%~dpn0.tmp"
findstr /R /I /C:"^%%F_[^_][^_]*_RSRQ_" "%~dpn0.tmp"
findstr /R /I /C:"^%%F_[^_][^_]*_SINR_" "%~dpn0.tmp"
findstr /R /I /C:"^%%F_[^_][^_]*_TX Power_" "%~dpn0.tmp"
findstr /R /I /C:"^%%F_[^_][^_]*_PCI_" "%~dpn0.tmp"
)
rem // Delete temporary file:
del "%~dpn0.tmp"
endlocal
exit /B
Relying on your example data, the aforementioned temporary file contains the following list:
Floor_1_SomeName_PCI_Some Trailing Text.JPG Floor_1_SomeName_RSRP_Some Trailing Text.JPG Floor_1_SomeName_RSRQ_Some Trailing Text.JPG Floor_1_SomeName_RSSI_Some Trailing Text.JPG Floor_1_SomeName_SINR_Some Trailing Text.JPG Floor_1_SomeName_TX Power_Some Trailing Text.JPG Floor_2_SomeName_PCI_Some Trailing Text.JPG Floor_2_SomeName_RSRP_Some Trailing Text.JPG Floor_2_SomeName_RSRQ_Some Trailing Text.JPG Floor_2_SomeName_RSSI_Some Trailing Text.JPG Floor_2_SomeName_SINR_Some Trailing Text.JPG Floor_2_SomeName_TX Power_Some Trailing Text.JPG
For every unique floor prefix consisting of Floor_
and a number, the above list is searched for the predefined keywords one after another in the proposed order. To get all the unique floor prefixes, an array-like variable set named $FLOOR_
, followed by the floor number, is used, whose respective values hold the floor prefix as they appear in the file names. For these prefixes to appear sorted in an alphanumerical manner, the floor number in the variable names are zero-padded to four digits:
$FLOOR_0001=Floor_1 $FLOOR_0002=Floor_2
The finally returned result is going to be this:
Floor_1_SomeName_RSSI_Some Trailing Text.JPG Floor_1_SomeName_RSRP_Some Trailing Text.JPG Floor_1_SomeName_RSRQ_Some Trailing Text.JPG Floor_1_SomeName_SINR_Some Trailing Text.JPG Floor_1_SomeName_TX Power_Some Trailing Text.JPG Floor_1_SomeName_PCI_Some Trailing Text.JPG Floor_2_SomeName_RSSI_Some Trailing Text.JPG Floor_2_SomeName_RSRP_Some Trailing Text.JPG Floor_2_SomeName_RSRQ_Some Trailing Text.JPG Floor_2_SomeName_SINR_Some Trailing Text.JPG Floor_2_SomeName_TX Power_Some Trailing Text.JPG Floor_2_SomeName_PCI_Some Trailing Text.JPG
Upvotes: 0
Reputation: 70923
@echo off
setlocal enableextensions disabledelayedexpansion
rem Retrieve folder from command line. By default current folder
for %%a in ("%~f1.") do set "folder=%%~fa"
rem Configure the order of the files
set /a "RSSI=1", "RSRP=2", "RSRQ=3", "SINR=4", "Tx=5", "PCI=6"
rem %%f - For each file in the indicated folder
rem %%a %%b %%c - Separate the elements of the file name
rem Use the elements to generate a serial number for the file
rem Output the serial number and the file name
rem Pipe the generated list into sort to sort on serial number
rem %%d Retrieve the sorted list
rem separate serial number and file name
rem output file name
(
for %%f in ("%folder%\Floor*") do @(
for /f "tokens=2,4 delims=_" %%a in ("%%~nxf") do @for /f %%c in ("%%b") do @(
set /a 10000000+%%a*100000+%%c
echo( %%~nxf
)
)
) | sort | for /f "tokens=1,*" %%d in ('findstr "^"') do @echo(%%e
Output
W:\41597911>dir /B *.jpg
Floor_1_SomeName_PCI_Some Trailing Text.JPG
Floor_1_SomeName_RSRP_Some Trailing Text.JPG
Floor_1_SomeName_RSRQ_Some Trailing Text.JPG
Floor_1_SomeName_RSSI_Some Trailing Text.JPG
Floor_1_SomeName_SINR_Some Trailing Text.JPG
Floor_1_SomeName_TX Power_Some Trailing Text.JPG
Floor_2_SomeName_PCI_Some Trailing Text.JPG
Floor_2_SomeName_RSRP_Some Trailing Text.JPG
Floor_2_SomeName_RSRQ_Some Trailing Text.JPG
Floor_2_SomeName_RSSI_Some Trailing Text.JPG
Floor_2_SomeName_SINR_Some Trailing Text.JPG
Floor_2_SomeName_TX Power_Some Trailing Text.JPG
W:\41597911>sortFiles.cmd
Floor_1_SomeName_RSSI_Some Trailing Text.JPG
Floor_1_SomeName_RSRP_Some Trailing Text.JPG
Floor_1_SomeName_RSRQ_Some Trailing Text.JPG
Floor_1_SomeName_SINR_Some Trailing Text.JPG
Floor_1_SomeName_TX Power_Some Trailing Text.JPG
Floor_1_SomeName_PCI_Some Trailing Text.JPG
Floor_2_SomeName_RSSI_Some Trailing Text.JPG
Floor_2_SomeName_RSRP_Some Trailing Text.JPG
Floor_2_SomeName_RSRQ_Some Trailing Text.JPG
Floor_2_SomeName_SINR_Some Trailing Text.JPG
Floor_2_SomeName_TX Power_Some Trailing Text.JPG
Floor_2_SomeName_PCI_Some Trailing Text.JPG
Upvotes: 3
Reputation: 67216
I don't used to post code when the OP did not posted his/her own efforts. However, this problem is rather interesting to me, so here it is a solution:
@echo off
setlocal EnableDelayedExpansion
set "order=RSSI RSRP RSRQ SINR "Tx Power" PCI"
rem Extract the "order" string into individual numerated elements
set "i=0"
for %%a in (%order%) do (
set /A i+=1
set "order[%%~a]=!i!"
)
rem Process the files and create an array with the desired order
set "lastFloor=0"
for /F "tokens=1-5 delims=_" %%a in ('dir /A:-D /B *.jpg') do (
set "name[%%b][!order[%%d]!]=%%a_%%b_%%c_%%d_%%e"
if %%b gtr !lastFloor! set "lastFloor=%%b"
)
rem Process the array elements
for /L %%i in (1,1,%lastFloor%) do (
for /F "tokens=2 delims==" %%a in ('set name[%%i]') do echo %%a
)
Output:
Floor_1_SomeName_RSSI_Some Trailing Text.JPG
Floor_1_SomeName_RSRP_Some Trailing Text.JPG
Floor_1_SomeName_RSRQ_Some Trailing Text.JPG
Floor_1_SomeName_SINR_Some Trailing Text.JPG
Floor_1_SomeName_TX Power_Some Trailing Text.JPG
Floor_1_SomeName_PCI_Some Trailing Text.JPG
Floor_2_SomeName_RSSI_Some Trailing Text.JPG
Floor_2_SomeName_RSRP_Some Trailing Text.JPG
Floor_2_SomeName_RSRQ_Some Trailing Text.JPG
Floor_2_SomeName_SINR_Some Trailing Text.JPG
Floor_2_SomeName_TX Power_Some Trailing Text.JPG
Floor_2_SomeName_PCI_Some Trailing Text.JPG
You may review the array management in Batch files at this answer.
Upvotes: 2