Create multiple URL shortcuts from a text file using a batch script [closed] - for-loop

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 28 days ago.
Improve this question
Summary: I have a set of reports I must to run, and would like to create links to each report online. The problem I'm having is how to make a batch file which can successfully loop through the file containing my URLs, and make an internet shortcut for each URL with a name based on data from URL itself.
Example URL exactly as shown, each URL is a line in a text file, (one report per day of the year):
<https://app.gomotive.com/en-US/#/reports/ifta-distance/vehicle;start_date=2023-01-01;end_date=2023-01-31;vehicle_ids=1103007;report_id=25;report_type=normal>
<https://app.gomotive.com/en-US/#/reports/ifta-distance/vehicle;start_date=2023-01-02;end_date=2023-01-31;vehicle_ids=1103007;report_id=25;report_type=normal>
<https://app.gomotive.com/en-US/#/reports/ifta-distance/vehicle;start_date=2023-01-03;end_date=2023-01-31;vehicle_ids=1103007;report_id=25;report_type=normal>
Breaking the URL down to understand the static vs dynamic data and how to manipulate it.
https://app.gomotive.com/en-US/#/reports/ifta-distance/vehicle;start_date= (static data)
2023-01-01 (dynamic data - format YYYY-mm-DD)
;end_date= (static data)
2023-01-31 (dynamic data - format YYYY-mm-DD)
;vehicle_ids=1103007;report_id=25;report_type=normal (static data)
I'm trying to make the URL shortcut names based off the line itself for example, with the URL https://app.gomotive.com/en-US/#/reports/ifta-distance/vehicle;start_date=2023-01-01;end_date=2023-01-31;vehicle_ids=1103007;report_id=25;report_type=normal, I'd like to create a shortcut in directory named: C:\Users\UserName\OneDrive\Desktop\Folder for the links\01-01-2023 mileage report.URL. The filename of 01-01-2023 being dynamic based on the date stated in the URL itself.
Also I found out the hard way, the other day, this computer "%UserProfile%\Desktop\Anywhere Else" is not a valid directory, not sure if this is a new Windows 11 trait, (moved from Win 7), or a OneDrive issue. Either way, any old code I had that used the %UserProfile% variable is needing re-done, or I need to make a new environment variable.
Here are my issue(s):
I have no experience using for looping command, let alone the restrictions of batch when using special characters. I thought I'd best ask before goofing something up terribly (special characters in the text file containing all the URLS).
The URL can vary on length ,so I'm not sure how to extract the month/day/year to use in the filename correctly.
Batch is the only language I have any experience with, and that is limited too. So whilst I'm sure there are much better options to do the task I'm wanting, I don't know them, to try them.
What I have done:
I used spreadsheet to break the URL down, modify the dates for the entire year, concatenate the data in a manner which made a proper working URL for each day of the year, added a column for the filename, and Echo #Echo Off> To the filename, Echo Start (the URL)>> To the filename, Echo Exit>> To the filename.
At which point, I was able to copy the crude columns of code from the spreadsheet, and paste them into the Command Prompt, which created a batch file for each URL, (file name was based on date) like so:
#Echo OFF
Start "" "https://app.gomotive.com/en-US/#/reports/ifta-distance/vehicle;start_date=2023-01-
01;end_date=2023-01-31;vehicle_ids=1103007;report_id=25;report_type=normal"
Exit
Making a working batch file for each link but surely not the right way to do it. (It's not the first time I've used a spreadsheet to break apart a directory or URL and re-constitute it for a batch file).
However I feel making actual internet shortcuts would be a much better way to do this across all forms of devices, (I think one of the people who may look at the reports from time to time use MacOS, and I'm assuming a batch file to "start" the URL won't work on their Mac, let alone not being the most friendly way of doing the job.
What my mind is telling me so far to do, (this is the batch file in my mind at the moment):
#Echo Off
CLS
REM Batch file create URLs based on text file
REM Filenames based on URL data from line in file
REM File containing URLs C:\Users\UserName\OneDrive\Desktop\Report Creation\FileNameOfURLS.txt
REM Save directory C:\Users\UserName\OneDrive\Desktop\Report Creation\All URLS Here
for /F "tokens=*" %%A in (C:\Users\UserName\OneDrive\Desktop\Report Creation\FileNameOfURLS.txt)
do (Echo [InternetShortcut] > "C:\Users\UserName\OneDrive\Desktop\Report Creation\%Option1%.URL"
echo URL=%%A >> "C:\Users\UserName\OneDrive\Desktop\Report Creation\%Option1%.URL"
echo IconFile=C:\Program Files\Google\Chrome\Application\chrome.exe >>
"C:\Users\UserName\OneDrive\Desktop\Report Creation\%Option1%.URL"
echo IconIndex=0 >> "C:\Users\UserName\OneDrive\Desktop\Report Creation\%Option1%.URL"
)
Exit
But I'm lost on how to extract the mm-DD-YYYY from the URL in the text file, and set it as the "option1", as I feel there is need for a second for command somewhere, to make this possible.
I have not ran my potential code, as shown above, through this system yet as I'm not sure how to make the filenames based on the data in the URL of the file filenames.txt, and I'm not sure this is even possible.
I did break the URLs down (365x) in spreadsheet, re-constitute them with proper dates, and make a column for filenames based on those dates, where I was able to further concatenate lines like Echo #Echo Off>FileName(s).bat, Echo Start "" "The URL with updated dates">>FileName(s).bat and Echo Exit>>FileName(s).bat, effectively creating a crude batch file containing the proper link, and having a correct name based on the date of the URL via the Command Prompt. However, making 365 batch files per year, and being locked to only Windows OS, not able to run those batch files on my phone either, makes them half as useful as if they were a .url file which any device can open.

Here is how I would think, based upon your provided text file content, and your unattempted code, it could be done:
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Set "URLFile=C:\Users\UserName\OneDrive\Desktop\Report Creation\FileNameOfURLS.txt"
Set "SaveDir=C:\Users\UserName\OneDrive\Desktop\Report Creation"
For /F "UseBackQ Delims=<>" %%G In ("%URLFile%") Do (
For /F "Tokens=3 Delims=;=" %%H In ("%%~G") Do (
Echo [InternetShortcut]
Echo URL="%%~G"
Echo IconFile="C:\Program Files\Google\Chrome\Application\chrome.exe"
Echo IconIndex=0
) 1>"%SaveDir%\%%H.url"
)
As you had assumed, an additional for loop was needed.
Please be aware however, that it is not very likely that your phone, or a Mac will have a copy of chrome.exe in the location stipulated in the IconFile entry. So you may be better advised to miss out those two Icon* keys, or at least their values.

Related

Reading & Writing a single line of a string variable to a text file in batch script..? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I'm making a small program/routine in batch script;
whereby I ask a user to input an ip address.
I want to take that input, & save it,
& load it the next time the program runs so that it could be processed without user inputting it again.
here's a summary/snippet of my code
:load
< lastip.txt (
I want to load %ip%
)
:choice
rem if lastip.txt exists
rem redirects user to somewhere
rem else goes to start depending upon user input
:start rem User inputs Ip here
cls
echo.
echo Input ip, its ipv4 I guess.
set /p %ip%="ip: "
goto save
:save
(
I want To save %ip%
) > lastip.txt
pause
goto somewhere
maybe this has been asked before but I wasn't able to implement any existing solutions in this use case; forgive me..
batch-scripting used to be so easy, maybe I'm not getting along with the syntax, hoping some one could help me on this holy platform?
edit:
initially I asked;
Saving & Loading a string variable in batch script..?
later I realized that saving and loading is not the same as reading and writing.. at least in my use case so I changed the question, Lol.
If you're just using one line of text file,
To save it as the first, and only line of your text file, use either
1> "lastip.txt" (Echo=%ip%)
OR
(Echo=%ip%) 1> "lastip.txt"
To load it from the first line of your text file,
use either
0< "lastip.txt" (Set /P "ip=")
OR
(Set /P "ip=") 0< "lastip.txt"
From textbook point of view; instead of saving & loading this is rather writing & reading from a text file using batch script if I'm not wrong but it should get the job done.
I would however be eager to know more on this if anyone else could redirect. that would be great.
thanks to #compo for the courtesy of this answer.

Retrieve CASE SENSITIVE Windows command 'whoami' Username [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I am using WinAutomation and I am trying to point to and open a file on any computer that my software is placed on without having to hard-code the username in the path, so I am looking for a way to retrieve the logged in Username, that will be case sensitive so I can grab that variable.
Using the Windows command line, (which I can run invisible to the user in the background) if the username in the file tree is "User Name", whoami will return "user name" and then,
If I point to a file C:\Users\%pcName%\Desktop\Masterlist.xlsx with that %pcName% not correctly capitalized it will not work...
I saw a question about Pythonic way to retrieve case sensitive path but I can't use Python for this. I am open to creative ways to get the case sensitive User Name but I keep seeing people deciding to enforce lowercase usernames as a solution.
Is there a way to find the case-sensitive logged in users name for use in file path references? I'm open to being creative at this point!!
First, let me make clear that your request is probably an XY issue. You're trying to achieve something and it looks like the solution is to fix the casing in the user name. However, there are several argument against that:
Windows file names are not case sensitive. It should not matter what casing you use. Maybe some other component compares these names in a case sensitive way where it shouldn't. In that case, the component should be fixed.
User names in Windows are not case sensitive. You can log on with any casing.
You're constructing a path C:\Users\%pcname%, which looks like %USERPROFILE%. However, a user profile is not necessarily in C:\Users. It could have been moved anywhere.
It's unclear to me, what exactly "does not work" and for which reason. You don't specify an error message which could let me diagnose the root cause, so we could fix the real problem.
You say that you can't use Python, but you do not specify any other programming language that you can use, so let me treat dos as an equivalent of batch.
Whatever your real problem is, echo %username% does what you ask for:
C:\Users\For example John>echo %username%
For example John
But be warned: in 90+% of the cases, this is not the correct approach.
In C#, you would use
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)
for the user profile and
Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
for the Desktop.
Winautomation has a function, "Get Special folder" that will return the filepath to the Desktop of the current PC as a variable. That variable can then be used as the root of whatever you are trying to access.
This is the correct way to reach the Desktop file path and does not require any special DOS usage.
'Desktop' is a User Shell Folder. The value for these folders is stored in the registry, with the right case :-).
The registry can be queried from the command prompt using 'reg query'.
If you just want the data value of the Desktop property, use the following:
for /f "tokens=2*" %a in ('reg query "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v Desktop ^| findstr "REG_"') do #echo %b

Batch Script wanted (windows). find substrings in text file, and make specific changes based on positions of characters

(This is a Windows environment by the way.)
I'm new to batch scripting and, I'll be honest, I'm struggling.
I've done a lot of googling and spent a lot of time trying to work this out but I'm not getting very far. I thought I'd throw this out to the community to see if anyone was up to the challenge. :)
First up, this is for my own personal use and curious interest to see if this is possible without writing a new .exe in a more... conventional language.
This is it : I'm using some software which is essentially portable. the only downside is that it writes to a .ini file very specific file paths which may not necessarily be correct if using another computer.
For example, if I run the software from a USB in Computer A, that computer might see the USB drive as D: and save a path in the ini as Path=D:\portables\soft1\saves\file1.xyz. But if I later use the same USB in Computer B which assigns a different letter to the drive (let's say E:) then the software will throw its toys out of the pram, because it's looking on the wrong drive for what should be now on E:. And if I run the software from a network drive or even cloud storage then the path's get even more complex.
I want to run a script that might, before running the software's .exe, look in the .ini for all instances of such filepaths and replace the full path with simply Path=.\saves\file1.xyz. The software is happy with this and can find what it needs to.
This is the ONLY thing that prevents the software being portable.
This is how I thought it would be done...
Search each line in the .ini, one at a time, to see if contains the
substring "Path="
If it finds it do the following...
a. Store the position of the character AFTER the "=" in "Path=" in a variable (let's say it's vPosA=6)
b. Search the same line for another substring "\saves\" and if it finds that then store the position of the character BEFORE the first "\" in another variable (let's say vPosB=18).
c. If vPosA and vPosB are both >0 then do the following
i. Replace all the characters on that line, from vPosA to vPosB, to "."
ii. Reset vPosA and vPosB both back to "0"
Go to the next line and repeat the process until the end of file is reached, then overwrite the .ini with the changes.
I'm looking forward to seeing what people come up with. Like I said, it's curiosity driving this. If I get no answer, or it's way way too complex I may just write the thing in VB or something and use a .bat to run it before running the software. The advantage of having it as a Batch Script is that it could shared with the software's community and the script is plain to see for all. With a compiled .exe people won't be able to see what's in it and would therefore, justifiably, distrust it.
This should do:
#echo off
setlocal enabledelayedexpansion
(for /f "tokens=*" %%a in (in.txt) do (
set "line=%%a"
if /i "!line:~0,5!"=="Path=" set "line=Path=!line:*\saves=.\saves!"
echo !line!
))>out.txt
type out.txt
Read every line, check if the first five characters are Path= (ignoring capitalization), if yes replace all from start to (including) "\saves" with ".\saves, append the string Path= in front of it. Print the line. Redirect the whole thing to another file.
You can then delete the original file and rename the new file to the old name.
NOTE: this ignores empty lines. It's possible to keep them with some more code.

Dos dir mask, want "*.xxx" and not "*.xxxzz"

In my directories, I have file names like *.xxx and also *.xxxzz
When I do dir /s/b "*.xxx" I get *.xxxzz files in my list. I do NOT get these results in a "Take Command" console, but I do in a cmd console.
How do I get cmd to give me only *.xxx files?
With the DIR command, when you specify a mask containing an extension of exactly three characters, you will get matches of files that contain extensions with three or more characters, so long as the first three characters match the extension you originally specified.
I have no idea why it works this way, but at least the behavior is consistent nearly everywhere in the Windows API where you can specify a file search pattern. I can only assume it has something to do with support for long file extensions (i.e., file names that don't comply with the old DOS 8.3 rule).
But, you can get around the behavior in two ways:
A mask that specifies a file extension with one, two, or more than three characters will return only files with extensions of exactly the specified length.
So, for example, dir /s/b "*.xx" will give you only files with the extension .xx, and dir /s/b "*.xxxzz" will give you only files with the extension .xxxzz.
You can use the question mark wildcard character, instead of the asterisk. Asterisks mean "replaced by zero or more characters", while question marks mean an exact substitution of the question mark with a single character.
I suspect you're running into a problem because of the way Windows (older versions, at least) generated a short 8.3 filename to improve compatibility with old programs. You can probably confirm this by doing dir /x *.xxx in the directory where your *.xxxzz files exist.
I'm not sure if there's a way around it from the limited Windows command line tools. There should probably have been a switch on the dir command to force consideration only of long filenames, but I don't see one.
You may be able to solve your problem by disabling short filenames on that volume, if you're sure you don't need them for any ancient software you're running.
I haven't tried that myself, so maybe the short names already generated will continue to exist after you follow those instructions. If so, you might be able to fix it by copying the tree you're working with to a new location.
The fact is that unless the system has been set up to not generate 8.3 names, every file or directory with a long filename will also have an 8.3 alias. At least one - with some of the warped constructs in use in later editions, there many be many aliases.
Academically, since it's a matter of opinion (and hence outside of SO's bailiwick) it could be argued that your alternative command processor is not producing the correct results since it apparently ignores the short filename. Which is "correct" is debatable - what suits in one application may not in another. The easiest and most logical way of course is to have an option - but the chances of the major player in the debate incorporating such a facility at this stage amount to well,Buckley's
Here's a routine that may suit. It's not bullet-proof as it will have problems with some "poison characters" (those with special meaning for the standard command-processor cmd.exe(A windows application that emulates and enhances many of the facilities available in DOS, and normally, though technically-incorrectly, called "DOS" by the politically-incorrect for the sake of brevity.))
#ECHO Off
SETLOCAL
SET "mask=%~1"
IF "%mask:~-4,1%"=="." ECHO(%mask:~-3%|FINDSTR /L "* ." >NUL&IF ERRORLEVEL 1 (
FOR /f %%a IN ('dir /s/b "%mask%"') DO IF /i "%%~xa"=="%%~sxa" ECHO(%%a
GOTO :EOF
)
dir /s/b "%mask%"
GOTO :EOF

Windows batch script to move lines from txt file to new file

I have a load of text files with some html code in them. EG:
Some random text....
..
...
....
<tag1>some more random text</tag1>
....
...
..
I need to run a script to go through each text file and move each line between the tags to a new text file in the same folder, and remove them from the original.
So the end result would be one file with no <tag1> and another file with only <tag1>.
I hope I made myself clear enough. Is this at all possible?
IF (and that is a big, bolded, italicized, capitalized IF) you can guarantee that each <tag1>...</tag> tag appears on a single line with no other content on that same line, and there are no tag attributes to complicate things, then the answer is easy.
Edit - fixed a number of bugs, it actually works now :-)
#echo off
for %%F in (*.txt) do (
echo processing %%F
findstr /rc:"^ *<tag1>.*</tag1> *$" "%%F" >"%%~nF.tag1%%~xF"
findstr /rvc:"^ *<tag1>.*</tag1> *$" "%%F" >"%%~nF.new%%~xF"
>nul move /y "%%~nF.new%%~xF" "%%F"
)
The solution could be extended to handle tag attributes fairly easily.
But I seriously doubt your problem is really that simple. Valid HTML content can have a tag spread accross many lines, and there can be many tags on one line.
Windows native batch is pretty lousy at text processing in general, and even worse for HTML or XML. I strongly recommend getting a third party tool like gnu sed for Windows that has robust text processing. Or better yet, get a tool that is specifically designed to process HTML.

Resources