0

Sorry for batch. Trying to keep this as simple as possible. I wrote a batch file whose shortcut I store in Window's "Send To" menu. It allows me to very quickly archive files & folders using any compression type I want (7z, nz, fp8, arc, etc). I've never used batch before writing this, so some of my code is unintuitive. It works though, so I'm happy. :^)

My method of detecting what file extension is selected is by looping through a list of manually-added extensions. If %~x1 matches with an extension in the list, it proceeds with the rest of the code. The problem is, if a folder has a name with symbols, it can break the detection of its extension. Periods(full-stops) and square-brackets definitely interfere.. other things probably do as well.
How can I get a selection's extension with a 100% success rate?
Alternatively, if there's a simpler way to check if %1 is a file or folder, that would be a suitable answer.
**Ideally I want this to stay 100% batch.
if other aspects of the code are nauseating, feel free to suggest changes to things unrelated to the question.

including code for anyone interested in the script or needs to take a look:

@echo off
setlocal EnableDelayedExpansion EnableExtensions
set sizebefore=0
set sizeafter=0
set nl=^&echo.
set "ext=nz"
set barline=---------------------------------------------------------------
::gets date+time (UTC) in order to give archives a unique name
for /f %%Y in ('wmic path win32_utctime get /format:list ^| findstr "="') do set %%Y
set today=%Year%%Month%%Day%
set tempname=%ext%TEMP%today%%Hour%%Minute%%Second%
for %%v in (".7z" ".ahk" ".aiff" ".aif" ".au" ".arc" ".avi" ".avif" ".bak" ".bat" ".bin" ".class" ".cfg" ".config" ".cpp" ".csv" ".cue" ".dat" ".dbf" ".dif" ".dll" ".doc" ".docx" ".eps" ".exe" ".fbt" ".fm3" ".fth" ".fp8" ".fpl" ".gif" ".gz" ".hqx" ".htm" ".html" ".ico" ".ini" ".inf" ".iso" ".ipynb" ".java" ".jpg" ".jpeg" ".js" ".json" ".log" ".m3u" ".m4a" ".m4v" ".mac" ".map" ".mdb" ".mid" ".midi" ".mkv" ".mov" ".mp3" ".mp4" ".msc" ".msi" ".mtb" ".mtw" ".nz" ".osz" ".otf" ".p65" ".pak" ".pdb" ".pdf" ".peace" ".png" ".ppt" ".pptx" ".psd" ".psp" ".py" ".qt" ".qxd" ".ra" ".rar" ".reg" ".resbackup" ".rmf" ".rtf" ".sfx" ".sit" ".sty" ".t65" ".tar" ".tar.gz" ".tdf" ".tex" ".tif" ".ts" ".txt" ".wav" ".webm" ".webp" ".wk3" ".wks" ".wpd" ".wg5" ".xls" ".xlsx" ".xml" ".zip") do (
    if /i "%~x1"=="%%~v" (
        echo File extension identified, {%~x1}%nl%
          if "%~x1"==".%ext%" cd "%~dp1" && nz x "%1" && ping -n 11 localhost >nul && exit
        set "archivename=%~n1-%today%"
        goto :loc_notfolder
    )
)
    ::error check. some names conflict with %~nx1 and produce a strange value.
    ::if an error occurs (ignoring unknown extensions), remove symbols from selection name
if not exist "%~dp1/%~nx1/" (
    echo Failed to identify selection.%nl%Please add the file extension to the list.%nl%
    goto :loc_info
) else (
    set "archivename=%~nx1-%today%"
    goto :loc_folder
)

::~~archiving files~~
::takes selected files, moves them into unique temp folder,
::archives that folder, then deletes it.
:loc_notfolder
for %%q in (%*) do set /a sizebefore+=%%~zq
echo Archiving as files%nl%%barline%
mkdir %~dp1%tempname% 2> NUL
for %%i in (%*) do xcopy "%%i*" "%~dp1%tempname%\"
cd "%~dp1%tempname%/"
echo Temp folder creation successful%nl%%barline%
nz a -r -cf -cc -m4g "%~dp1%tempname%.%ext%" "%~dp1%tempname%"
if exist "%~dp1%tempname%.%ext%" (
  cd "%~dp1%"
  echo %barline%%nl%Compression successful%nl%Deleting temp folder...%nl%
  rmdir /s /q "%~dp1%tempname%"
  goto :loc_rename
) else (
  goto ::loc_info
)

::~~archiving folder~~
::simple recursive method. no temp files/folders
:loc_folder
::loop to get size of folder. sometimes fails. whatever
set target=%~1
for /f "tokens=3,5" %%a in ('
  dir /a:d /s /w /-c "%target%"
  ^| findstr /b /l /c:"  "
') do if "%%b"=="" set sizebefore=%%c

echo No files selected.%nl%%nl%Archiving as folder%nl%%barline%
cd "%~dp1/%~nx1"
nz a -r -cf -cc -m4g "%~dp1%tempname%.%ext%" "%~dp1%~nx1"
goto :loc_rename



:loc_rename
::storing size of the new archive
for %%g in ("%~dp1%tempname%.%ext%") do set sizeafter=%%~zg

::check if archive already exists. yes=>skip renaming loop
if not exist "%~dp1%archivename%.%ext%" (
  ren "%~dp1/%tempname%.%ext%" "%archivename%.%ext%"
  goto :loc_end
)

::loop to generate an archive that doesn't already exist
set "ncount=1"
:loc_loop
if exist "%~dp1/%archivename%_%ncount%.%ext%" (
  set /a ncount+=1
  goto :loc_loop
)
::attaching value to the desired archive name
set archivename=%archivename%_%ncount%
ren "%~dp1/%tempname%.%ext%" "%archivename%.%ext%"


:loc_end
echo %nl%%nl%%barline%
echo File: %archivename%.%ext%
echo Path: %~dp1%archivename%.%ext%
echo Before: %sizebefore%B
echo After: %sizeafter%B
echo %barline%%nl%

ping -n 11 localhost >nul
exit

::redirect here to check for path problems
:loc_info
echo "~dp0" {%~dp0}%nl%"~dp1" {%~dp1}%nl%"~dp2" {%~dp2}%nl%"~dp3" {%~dp3}%nl% "~p0" {%~p0}%nl% "~p1" {%~p1}%nl% "~p2" {%~p2}%nl% "~p3" {%~p3}%nl% "~n0" {%~n0}%nl% "~n1" {%~n1}%nl% "~n2" {%~n2}%nl% "~x0" {%~x0}%nl% "~x1" {%~x1}%nl% "~x2" {%~x2}%nl% "~x3" {%~x3}%nl%"~nx1" {%~nx1}%nl%"~nx2" {%~nx2}%nl%"~nx3" {%~nx3}%nl%"~fs0" {%~fs0}%nl%"~fs1" {%~fs1}%nl%"~fs2" {%~fs2}%nl%"~fs3" {%~fs3}%nl% "~f0" {%~f0}%nl% "~f1" {%~f1}%nl% "~f2" {%~f2}%nl% "~f3" {%~f3}%nl%"~fp0" {%~fp0}%nl%"~fp1" {%~fp1}%nl%"~fp2" {%~fp2}%nl%"~pn0" {%~pn0}%nl%"~pn1" {%~pn1}%nl%"~pn2" {%~pn2}%nl%"~pn3" {%~pn3}%nl%
pause
exit
Dan Mašek
  • 17,852
  • 6
  • 57
  • 85
snowbie
  • 9
  • 3
  • Temporarily change your script content to **1.** `@echo off`, **2.** `setlocal EnableDelayedExpansion EnableExtensions`, **3.** `echo("%~1" - "%~x1" - "%*"`, **4.** `pause`, **5.** `exit`. Then use it in the same manner, with the same working and problematic files, and make a note of the output it shows you. Hopefully that should give you some insight into what is actually being passed to your script via the Send To process. – Compo Dec 18 '20 at 03:51
  • I left echo on during most of the writing as things broke frequently. I could have posted a debug-version, but the code in its current state will send the user to `loc_rename` at the bottom if it's unable to recognize a file extension. It does this check immediately after parsing through the list of known file extensions. When extensions are considered unknown, `%~x1` can return values like `.backup` if `%~1` is `.../stackoverflow.2020.backup/` Upon further testing, I noticed this **only happens with folders**. It makes sense since files always end with their associated extension. – snowbie Dec 18 '20 at 04:18
  • [Here's what it returns](https://i.imgur.com/ng9yUvA.png) when trying to archive `Desktop\test[test].test.test.whatever\ `. It's a folder being labeled as an unknown file because `%~x1` returns `.whatever` This makes my post's title a bit misleading because now it's a problem associated with folder; files seem to be fine. – snowbie Dec 18 '20 at 04:24
  • Clearly you need to change your batch file, so that it determines whether the input is a file or a directory, then create the relevant condition for each as necessary. As that input is being sent via the Send To menu, it should always exist, and therefore its directory attribute, _(or lack of it)_, could be used to assist in that decision. – Compo Dec 18 '20 at 05:00
  • Checking for a folder sure is a lot easier... dunno why I prioritized file detection so much. Thanks. I'll update the post with the revised code. – snowbie Dec 18 '20 at 05:59

1 Answers1

0

Would %~sp1 remove the special characters in the file name and still have the correct extension? Then do %~x on the 8.3 result?

https://ss64.com/nt/syntax-args.html
%~sp1 Expand %1 to a path shortened to 8.3 characters

Ss64.com is my go-to site for DOS stuff.

I apologize for not testing this, I don't have a Windows machine available at the moment.


update

Consider using %~sx1

%~s1 Change the meaning of f, n, s and x to reference the Short 8.3 name (if it exists.)