Link to home
Start Free TrialLog in
Avatar of defecta
defectaFlag for Australia

asked on

Batch command to return string from line 'X' in a file or preferably piped input

Hi guys,

I am writing a little batch file for clearing the preferences (deleting the contents of a settings folder) from Adobe Illustrator when things go south and it starts to flake out (which happens frequently enough to necessitate this batch file unfortunately).

We have a have a few different versions of CS in use so the name of the folder changes with the version. I am writing this batch file so that its intelligent enough to find the folder without me having to program the different versions into the batch file. Also in the instance where it finds more than 1 version installed, it asks the user which version it wants to clear the preferences from.

Where I am stuck is trying to find a batch command that will allow me to echo 'X' line from some piped input like a
dir /b /ad %userprofile%\AppData\Roaming\Adobe\Adobe Illustrator CS*

Open in new window

and only return the line I choose.

Is this possible without any other dependencies or software required?

I have looked at FIND and FINDSTR and I cant see that either can be used for this purpose. But that doesn't mean I'm right about that. =]

Thanks in advance folks.
Avatar of oBdA
oBdA

You can do that by counting the lines:
@echo off
setlocal enabledelayedexpansion
set Line=2
set Folder=%userprofile%\AppData\Roaming\Adobe\Adobe Illustrator CS*
set /a i=0
for /f "delims=" %%a in ('dir /b /a:d "%Folder%"') do (
	set /a i+=1
	if "!i!"=="%Line%" echo %%a
)

Open in new window

Or you can use find's "/n" and find non-empty lines, then look for the line number:
@echo off
setlocal
set Line=2
set Folder=%userprofile%\AppData\Roaming\Adobe\Adobe Illustrator CS*
for /f "tokens=1* delims=[]" %%a in ('dir /b /a:d "%Folder%" ^| find /v /n ""') do (
	if "%%a"=="%Line%" echo %%b
)

Open in new window

Here's another approach that will work well, utilizing builtin FIND and FINDSTR commands:

@echo off
set BaseDir=d:\ee\ee*
set Line=5
for /F "tokens=1* delims=]" %%A in ('dir /b /ad "%BaseDir%"^|find /v /n ""^|findstr /r /b /c:\[%Line%\]') do set DirName=%%B
echo %DirName%

Open in new window

The basic idea is run the DIR to get the list of folders, then pipe that into the FIND to add line numbers to the left of each line, then pipe that into FINDSTR to find the line number we want (line numbers are at the left of the line in []), and then use the outer FOR /F to separate the original line stuff from the line number to assign it to a variable.

~bp
Avatar of defecta

ASKER

Thanks for the quick reply guys.

I have been doing this to count the number of lines before going through the routine that prompts for clearing multiple folders.

For /f "tokens=* %%a IN ('dir /b %userprofile%\Appdata\Roaming\Adobe\Adobe Illustrator CS*^| Find  /c /v ""') DO IF %%a GTR 1 @echo There are multiple installations of CS

Open in new window


I then planned to read back each line from the 'dir' command, prompt the user to clear the folder with Y or N, increment the line count by +1, read the next line and prompt etc, until the line count equals %%a and then quit.

To use the code you guys have suggested I would need to substitute the value for %Line% with a variable also woudn't I?
You don't need to count lines for that, as you're already processing the folder subfolder by subfolder. Try something like this:
@echo off
setlocal enabledelayedexpansion
set Folder=%userprofile%\AppData\Roaming\Adobe\Adobe Illustrator CS*
for /f "delims=" %%a in ('dir /b /a:d "%Folder%"') do (
	echo Processing %%~fa ...
	set Clear=
	set /p Clear=Do you want to clear this installation folder? [y^|N]
	if /i "!Clear!"=="Y" (
		echo Clearing %%a ...
		REM Clear the settings folder in this line;
		REM The current folder name will be in "%%a", the full folder name in ""%Folder%\%%a"
	)
)

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of oBdA
oBdA

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of defecta

ASKER

Damn dude, thank you so much! That does exactly what I need with way more flair than what I could do at this point in time!<br /><br />I'm reading over your code it mostly makes sense to me. If I can ask for the benefit of my learning, on line 10 near the end of the line there are some characters that I don't understand or haven't seen before. Its the "~nx" in "%%~nxa". What does that do?
Props to oBdA, love it.

~bp
Avatar of defecta

ASKER

OK it should already be pretty clear that I am a noob at this but deleting the files from a folder should be a cinch but I am getting
The system cannot find the path specified.

when using the %CSFolder%\%ClearFolder%\en_GB for the path.

I have tested this on a test folder C:\test (works fine) which made me think I must have a permissions issue but running the batch as 'Administrator' didn't help.

I also tried 'run as' with a domain admin account and the batch wont even run at all. The batch window closes as quickly as it opens.

Something I don't understand is preventing me from finding/deleting the files and folders from this path. (I have no AV installed currently, so that cant be to blame either.)

EDIT: Never mind. I think I know what I was doing wrong. I am forgetting the " " around the path.
Avatar of defecta

ASKER

Yep, its official. I'm a noob. I was missing the quotes. lol.

Thanks again!
Avatar of defecta

ASKER

found a new problem though.

I'm trying to duplicate your code again in the ClearFolder section and its not working the way I want.

Entering 'Y' the first time doesn't work but all subsequent attempts work fine. I thought I needed to set or clear the Clear64 variable but that doesn't seem to help.

Your infinite wisdom would be much appreciated. Here is the code I am working with.
:ClearFolder
set ClearFolder=!CS[%1]!
REM echo Clearing '%ClearFolder%' ...
REM Add your clearing code here.
REM The settings folder name will be in %ClearFolder%;
REM to access the full path, use "%CSFolder%\%ClearFolder%"

set CSdir=%CSFolder%\%ClearFolder%
for /f "tokens=*" %%b IN ('dir /b /ad "%CSDir%" ^| find "en_"') do set Lang=%%b
echo Clearing settings from folder "%ClearFolder%"
if EXIST "%CSDir%\%Lang%\x64\" (
echo ----------------------------------------------------------------------
echo %TAB%There is also a 64 bit version of Illustrator installed.
echo %TAB%If you are using the 64 bit version and you want to clear
echo %TAB%these settings press Y then Enter.
echo %TAB%Press X then Enter to exit.
echo ----------------------------------------------------------------------
set Clear64=
set /p Clear64=^>
if "%Clear64%"=="" goto ClearFolder
if /i "%Clear64%"=="X" goto Done
if /i "%Clear64%" NEQ "Y" goto ClearFolder 
echo Yay, you chose to delete.
)
pause

Open in new window

This should support the x64 installations as well; these will be treated the same as the x86 installations, as far as the menu is concerned.
Important change: the variable %ClearFolder% in the "ClearFolder" subroutine now contains the full/absolute path; for 32bit, this will be the same as the former "%CSFolder%\%ClearFolder%", for 64bit it will go all the way down to the %lang%\x64 folder.
The "%%~nxa" will expand to the name and extension of the file/folder in the variable %%a; enter "help call" for details.
@echo off
setlocal enabledelayedexpansion
set CSFolder=%userprofile%\AppData\Roaming\Adobe
set Mask=Adobe Illustrator CS*
set TAB=	
set ContainsX64=0
set /a InstallCount = 0
echo Scanning for CS installation settings ...
for /d %%a in ("%CSFolder%\%Mask%") do (
	set /a InstallCount += 1
	set CSMenu[!InstallCount!]=%%~nxa
	set CSDir[!InstallCount!]=%%a
	set CSArch[!InstallCount!]=32bit
	set Cleared[!InstallCount!]=-
	set Lang=$$$
	for /f "tokens=*" %%b in ('dir /b /ad "%%a" ^| find "en_"') do set Lang=%%b
	if exist "%%a\!Lang!\x64" (
		set ContainsX64=1
		set /a InstallCount += 1
		set CSMenu[!InstallCount!]=%%~nxa
		set CSDir[!InstallCount!]=%%a\!Lang!\x64
		set CSArch[!InstallCount!]=64bit
		set Cleared[!InstallCount!]=-
	)
)
if %InstallCount% EQU 0 (
	echo No CS installation settings found.
	goto Done
)
if %InstallCount% EQU 1 (
	call :ClearFolder 1
	goto Done
)
:Menu
echo.
echo %InstallCount% CS installation settings have been found.
if "%ContainsX64%"=="1" (
	echo These include at least one x64 installation;
	echo please pay attention to the architecture you want to clear.
)
echo ----------------------------------------------------------------------
echo Index%TAB%Clear%TAB%Arch.%TAB%Folder
echo ----------------------------------------------------------------------
for /l %%i in (1, 1, %InstallCount%) do (
	echo %%i%TAB%!Cleared[%%i]!%TAB%!CSArch[%%i]!%TAB%!CSMenu[%%i]!
)
echo ----------------------------------------------------------------------
echo Please choose the installation index to clean, or X to exit:
set Index=
set /p Index=^>
if "%Index%"=="" goto Menu
if /i "%Index%"=="X" goto Done
if %Index% LSS 1 goto Menu
if %Index% GTR %InstallCount% goto Menu
call :ClearFolder %Index%
set AllCleared=1
for /l %%i in (1, 1, %InstallCount%) do (if "!Cleared[%%i]!"=="-" set AllCleared=0)
if %AllCleared%==0 goto Menu
:Done
echo Done.
goto :eof
REM ======================================================================
:ClearFolder
set ClearName=!CSMenu[%1]!
set ClearFolder=!CSDir[%1]!
set ClearArch=!CSArch[%1]!
echo Clearing %ClearArch% installation of '%ClearName%' ...
echo Full path: '%ClearFolder%'
REM Add your clearing code here.
REM The absolute settings folder path will be in %ClearFolder%;
REM If you need to check the installation architecture, use %ClearArch%, which will be either '32bit' or '64bit'.

set Cleared[%1]=X
goto :eof

Open in new window

Avatar of defecta

ASKER

Thanks so much again oBda.

It's funny because I was thinking about this problem this morning before I woke up and thought about solving it exactly how you just did. =)
Avatar of defecta

ASKER

Can I just say again what an amazing piece of work oBda? Thanks again.