I am doing a simple batch file to copy folders and files located under the same path of the batch files to the desktop. I can easily get the path where the batch file is located using
%~dp0
but I want to know how to get the path of the user's desktop (I am using Widows 7 Ultimate)
Any suggestions?
I suppose you're under windows environnement, so %USERPROFILE%\Desktop should be ok
This is the location of the current users desktop:
%userprofile%\desktop
If Desktop locations in a different folder only this will be correct answer:
Batch string:
for /f "usebackq tokens=3*" %%D IN (`reg query "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v Desktop`) do set DESKTOP=%%D
V2 (Works with spaces) 4.10.2016:
for /f "usebackq tokens=1,2,*" %%B IN (`reg query "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v Desktop`) do set DESKTOP=%%D
If you have non-ASCII symbols, you also need to convert ANSI encoding to OEM, example for cyrillic:
CHCP 1251 >Nul
for /f "usebackq tokens=1,2,*" %%B IN (`reg query "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v Desktop`) do set DESKTOP=%%D
CHCP 866 >Nul
for /f "delims=" %%i IN ('echo %DESKTOP%') do set DESKTOP=%%i
Then just use:
echo %DESKTOP%
I think this one should be ok too
%systemdrive%\Documents and Settings\All Users\Desktop
Regards
I found the answer
Regedit /e /a dd.txt
"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
find /i dd.txt "Desktop" >d.txt
For /F "tokens=2 delims==" %%a in (d.txt) do set mydesktop=%%a
The default for the Windows desktop directory of current user is defined with %USERPROFILE%\Desktop. USERPROFILE is one of the predefined Windows environment variables.
So it would be possible to use just the following folder path:
"%UserProfile%\Desktop"
But it would be better to get the desktop directory path from Windows registry instead of using simply the default. There are two registry keys containing a string value with name Desktop with the path to user's desktop directory:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
This registry key contains several string values usually of type REG_EXPAND_SZ which define the paths to the various shell folders defined for the current user account. The shell folders contain usually an environment variable reference like %USERPROFILE% which is the reason for the type REG_EXPAND_SZ which means the string value must be additionally expanded to get absolute path to the shell folder. The batch file below expands the environment variable reference by using the command CALL to force one more command line parsing by Windows command processor.
For example, the command set "DesktopFolder=%%~K" becomes first on execution of for the command set "DesktopFolder=%USERPROFILE%\Desktop". This command is parsed a second time by cmd.exe to something like set "DesktopFolder=C:\Users\UserName\Desktop" because of the command call before really executing the command set to define the environment variable DesktopFolder with the real absolute folder name read from the Windows registry.
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders
This registry key contains nearly the same string values as the registry key above, but the string values are usually of type REG_SZ. This registry key is for downwards compatibility for applications not supporting the other registry key with the string values with environment variable references.
It is possible that a shell folder is defined only in one of the two registry keys. For example on Windows XP the string values Administrative Tools, CD Burning, Fonts and Recent exist only under registry key Shell Folders and do not exist under key User Shell Folders.
Information added by Compo with comments below my similar answer on:
How to create a directory in the user's desktop directory?
Windows itself uses by default the string values defined under key User Shell Folders and uses a string value defined under key Shell Folders only if not existing under key User Shell Folders.
Windows does not propagate a modification on a string value under key User Shell Folders to the string value with same name under key Shell Folders if a user or a program modifies directly in registry a string value under key User Shell Folders without making appropriate change to key with same name under key Shell Folders.
So in case of Desktop in User Shell Folders contains a different directory path than Desktop in Shell Folders, Windows uses the path defined with Desktop in User Shell Folders.
A user has the freedom to change any folder to whatever the user wants. But the user must take care to change a string value in both registry keys on existing twice. Some of the shell folders can be easily modified via an option on graphical user interface of Windows or a Windows application like the Downloads shell folder.
See also the Microsoft documentations for Known Folders and KNOWNFOLDERID and the other documentation pages referenced on these pages as well as the documentation about Application Registration.
Here is a batch file which gets the user's desktop directory from Windows registry as much safe as possible.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "DesktopFolder="
for /F "skip=1 tokens=1,2*" %%I in ('%SystemRoot%\System32\reg.exe QUERY "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v Desktop 2^>nul') do if /I "%%I" == "Desktop" if not "%%~K" == "" if "%%J" == "REG_SZ" (set "DesktopFolder=%%~K") else if "%%J" == "REG_EXPAND_SZ" call set "DesktopFolder=%%~K"
if not defined DesktopFolder for /F "skip=1 tokens=1,2*" %%I in ('%SystemRoot%\System32\reg.exe QUERY "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v Desktop 2^>nul') do if /I "%%I" == "Desktop" if not "%%~K" == "" if "%%J" == "REG_SZ" (set "DesktopFolder=%%~K") else if "%%J" == "REG_EXPAND_SZ" call set "DesktopFolder=%%~K"
if not defined DesktopFolder set "DesktopFolder=\"
if "%DesktopFolder:~-1%" == "\" set "DesktopFolder=%DesktopFolder:~0,-1%"
if not defined DesktopFolder set "DesktopFolder=%UserProfile%\Desktop"
echo User's desktop folder is: %DesktopFolder%
endlocal
This batch file works even on Windows XP on which reg.exe outputs the results of the query different to reg.exe of Windows Vista and newer Windows versions.
See Microsoft article about Using command redirection operators for an explanation of 2>nul which redirects the error message output by command MD on directory already existing to handle STDERR to the device NUL to suppress this error message.
However, the user's desktop directory should contain only shortcut files (*.lnk files) and the files and directories created by the user on the desktop. No program should create ever other files than shortcut files in the user's desktop directory. Microsoft defined several other shell folders for applications like APPDATA (application data) or LOCALAPPDATA (local application data) for applications.
Some additional facts about handling of string value Desktop under the keys User Shell Folders and Shell Folders by Windows as observed with Windows XP SP3 x86 with always restarting Windows after making a change in registry hive of current user:
A change of the path string of the string value Desktop under the key User Shell Folders for example from %USERPROFILE%\Desktop to %USERPROFILE%\MyDesktop and of course creation of the directory %USERPROFILE%\MyDesktop changes the Windows desktop directory to custom %USERPROFILE%\MyDesktop on next log on and the string value of Desktop under key Shell Folders is adapted by Windows on next restart. It was not tested by me if Desktop under the key Shell Folders is adapted also on just doing a log off and log on. It is definitely better to change both Desktop string values at the same time to change the desktop directory permanently to a directory different from default %USERPROFILE%\Desktop.
A removed or renamed string value Desktop under the key User Shell Folders is never recreated by Windows. So it is possible that this string value does not exist if Desktop under the key User Shell Folders was by mistake once deleted or renamed or the registry file is partly damaged with the result that this string value does not exist. A user would not notice that issue as the further tests below showed.
The string value Desktop of type REG_SZ under key Shell Folders is always set to expanded path of %USERPROFILE%\Desktop if string value Desktop of type REG_EXPAND_SZ under key User Shell Folders does not exist at all. Windows creates also the directory %USERPROFILE%\Desktop automatically if not existing in this error handling case
If the string value Desktop of type REG_SZ under key Shell Folders and the string value Desktop of type REG_EXPAND_SZ under key User Shell Folders are both deleted or renamed by a user or program, Windows creates on next start the string value Desktop of type REG_SZ under key Shell Folders with expanded path of %USERPROFILE%\Desktop and creates also the directory if not existing. The string value Desktop of type REG_EXPAND_SZ under key USer Shell Folders is not recreated by Windows.
If the string value Desktop of type REG_SZ under key Shell Folders exists with a different expanded path than %USERPROFILE%\Desktop like expanded path of %USERPROFILE%\MyDesktop and the string value Desktop of type REG_EXPAND_SZ under the key User Shell Folders does not exit at all, Windows ignores the customized path of Desktop of type REG_SZ under the key Shell Folders and sets the value to expanded path of %USERPROFILE%\Desktop and creates additionally the directory %USERPROFILE%\Desktop if not already existing. So it is not possible to use a customized desktop directory without having the customized desktop directory defined also with string value Desktop of type REG_EXPAND_SZ under the key User Shell Folders.
I did not make tests with newer versions on Windows regarding to handling of Desktop under the keys Shell Folders and User Shell Folders if one or both string values do not exist and/or have same or different directory paths and/or have a directory path different to default.
Cleanest solution just for Desktop:
for /f "tokens=2*" %%a in ('reg query "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v Desktop') do set DESKTOP=%%b
echo %DESKTOP%
tokens=Type (2), then remaining Data (*) so location whitespace isn't tokenized. (spaces are allowed)
But if you're looking for any registry value which may not exist:
#echo off
set SUBKEY=HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
set VALUE_NAME=Desktop
for /f "tokens=*" %%a in ('reg query "%SUBKEY%" /v "%VALUE_NAME%" 2^>nul') do set LINE=%%a
if defined LINE goto else
echo "%VALUE_NAME%" value not found.
goto end
:else
for /f "tokens=2,3 delims=#" %%a in ("%LINE: =#%") do (
echo Key: %SUBKEY%
echo Name: %VALUE_NAME%
echo Type: %%a
echo Data: %%b
)
:end
echo[
pause
tokens=* gets the whole line (Name + Type + Data) which are separated by 4 spaces
%LINE: =#% replaces the 4 spaces with hashtags so we can deliminate the tokens properly
tokens=2,3 gets us the Type and Data fields which get put into %%a and %%b
If you just want the Data you can do tokens=3 and it'll be in %%a. (since it's the only token)
Of all the examples i've been looking at all over the web, i haven't seen anyone else collecting the whole line and swapping the 4 spaces so they can tokenize properly. They all let it split at every whitespace, which can exist at both the Name and the Data fields. Of course if you're just after a specific value however (like "Desktop") you know the Type will be the 2nd token, and the remaining Data (*) is the last token. If you wanted a one liner for "My Pictures", you'd do token=3* instead. ("My" "Pictures" "Type" (3) "Data" (*))
Also the 2^>nul simply prevents the reg query command telling us if the value doesn't exist.
I reccomend to use this script:
#echo off
if exist "%userprofile%\OneDrive\Desktop" (chdir %userprofile%\OneDrive\Desktop) else (chdir %userprofile%\Desktop)
If someone installed OneDrive on windows setup, their desktop will probably be located under OneDrive folder. Else it will be User\Desktop.
Environ("USERPROFILE") & "\Desktop"
Related
I need some advice on my plan to create a script file to delete certain files (log files( in the AppData subfolder. the logs is auto generated daily and save in their AppData folder
My plan is:
only to delete a log files inside the log folder that the age more than 10days and remain the new logs inside the folder.
My problem is, there are some folder before the logs folder generated different on each customer. Here the example of 2 sample customer that using the application. The bold subfolder is auto generated folder by system and on each user, it create a random subfolder name except for the last Folder Logs. The logs files that I want to create a script to delete is reside in the Logs folder.
C:\Users\zulhadi\AppData\Local\Apps\2.0\TOHH10RY.RPR\1TK3RWZA.7LL\tmov..tion_c53c7abfec4c3d4d_0001.000c_3bf64a70373000ba\Logs
C:\Users\ainul\AppData\Local\Apps\2.0\ALR6MXVO.1Q5\EXHY50X4.TDT\tmov..tion_c53c7abfec4c3d4d_0001.000c_3bf64a70373000ba\Logs
My question is:
Any idea how can I create a script that delete the logs files in the logs folder if the situation like below as explain. I'm not a very computer background and not very familiar about scripting but do have see some video/tutorial over internet on this basic of scripting of deleting the folder in windows 10.
#ECHO OFF
SETLOCAL
rem The following setting for the source directory is a name
rem that I use for testing and deliberately includes spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.
SET "sourcedir=u:\your files"
FOR /d /r "%sourcedir%" %%b IN (*) DO IF /i "%%~nxb"=="logs" (
rem for each logs directory found, get a list of the .log files
rem sorted in reverse-date order. Skip the first 10 (newest) and delete the rest
FOR /f "skip=10delims=" %%e IN ('dir /b /a-d /o-d "%%b\*.log" 2^>nul') DO ECHO DEL "%%b\%%e"
)
GOTO :EOF
Always verify against a test directory before applying to real data.
The required DEL commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO DEL to DEL to actually delete the files.
Perform a recursive listing of the directorynames starting at the chosen sourcedir (See for /? from the prompt for documentation) and select only those with a "leafname" (final element of the full directoryname) of logs. The full directoryname found is in %%b.
With each such directoryname, perform a directory list of the *.log files using dir producing names-only (/b) and no directorynames (/a-d) in order of reverse-date (/o-d) - see dir/? from the prompt for documentation.
We need the full name reported by dir, so delims is set to nothing, and we need to skip the first 10 lines of the report since we wish to retain the latest 10 files which are the first 10 lines returned as the report is sorted in reverse-date order.
The 2^>nul suppresses the error report generated by dir should there be no matching filenames in the directory. The caret is used as an "escape" character to tell cmd that the > redirector forms part of the dir command, not the for.
So I am making a batch file that I will put in the startup folder. I need to make a directory in the desktop directory of current user. I only know how to make a new directory in the current directory.
The only way I know how to make a directory is with the command mkdir.
The default for the Windows desktop directory is defined with %USERPROFILE%\Desktop. USERPROFILE is one of the predefined Windows environment variables.
So it would be possible to use just:
md "%UserProfile%\Desktop\NewDirectory" 2>nul
That would create a directory with name NewDirectory on user's desktop as long as the user has not changed the default for the desktop directory. The command md can be use with a full qualified directory path or a relative directory path. The help output on running in a command prompt md /? explains that md creates the entire directory tree to a directory not existing if command extensions are enabled as by default. See also the Microsoft documentation for naming files, paths, and namespaces.
But it would be better to get the desktop directory path from Windows registry instead of using simply the default. There are two registry keys containing a string value with name Desktop with the path to user's desktop directory:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
This registry key contains several string values usually of type REG_EXPAND_SZ which define the paths to the various shell folders defined for the current user account. The shell folders contain usually an environment variable reference like %USERPROFILE% which is the reason for the type REG_EXPAND_SZ which means the string value must be additionally expanded to get absolute path to the shell folder. The batch file below expands the environment variable reference by using the command CALL to force one more command line parsing by Windows command processor.
For example, the command set "DesktopFolder=%%~K" becomes first on execution of for the command set "DesktopFolder=%USERPROFILE%\Desktop". This command is parsed a second time by cmd.exe to something like set "DesktopFolder=C:\Users\UserName\Desktop" because of the command call before really executing the command set to define the environment variable DesktopFolder with the real absolute folder name read from the Windows registry.
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders
This registry key contains nearly the same string values as the registry key above, but the string values are usually of type REG_SZ. This registry key is for downwards compatibility for applications not supporting the other registry key with the string values with environment variable references.
It is possible that a shell folder is defined only in one of the two registry keys. For example on Windows XP the string values Administrative Tools, CD Burning, Fonts and Recent exist only under registry key Shell Folders and do not exist under key User Shell Folders.
Information added by Compo:
Windows itself uses by default the string values defined under key User Shell Folders and uses a string value defined under key Shell Folders only if not existing under key User Shell Folders.
Windows does not propagate a modification on a string value under key User Shell Folders to the string value with same name under key Shell Folders if a user or a program modifies directly in registry a string value under key User Shell Folders without making appropriate change to key with same name under key Shell Folders.
So in case of Desktop in User Shell Folders contains a different directory path than Desktop in Shell Folders, Windows uses the path defined with Desktop in User Shell Folders.
A user has the freedom to change any folder to whatever the user wants. But the user must take care to change a string value in both registry keys on existing twice. Some of the shell folders can be easily modified via an option on graphical user interface of Windows or a Windows application like the Downloads shell folder.
See also the Microsoft documentations for Known Folders and KNOWNFOLDERID and the other documentation pages referenced on these pages as well as the documentation about Application Registration.
Here is a batch file which gets the user's desktop directory from Windows registry as much safe as possible.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "DesktopFolder="
for /F "skip=1 tokens=1,2*" %%I in ('%SystemRoot%\System32\reg.exe QUERY "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v Desktop 2^>nul') do if /I "%%I" == "Desktop" if not "%%~K" == "" if "%%J" == "REG_SZ" (set "DesktopFolder=%%~K") else if "%%J" == "REG_EXPAND_SZ" call set "DesktopFolder=%%~K"
if not defined DesktopFolder for /F "skip=1 tokens=1,2*" %%I in ('%SystemRoot%\System32\reg.exe QUERY "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v Desktop 2^>nul') do if /I "%%I" == "Desktop" if not "%%~K" == "" if "%%J" == "REG_SZ" (set "DesktopFolder=%%~K") else if "%%J" == "REG_EXPAND_SZ" call set "DesktopFolder=%%~K"
if not defined DesktopFolder set "DesktopFolder=\"
if "%DesktopFolder:~-1%" == "\" set "DesktopFolder=%DesktopFolder:~0,-1%"
if not defined DesktopFolder set "DesktopFolder=%UserProfile%\Desktop"
md "%DesktopFolder%\NewDirectory" 2>nul
endlocal
This batch file works even on Windows XP on which reg.exe outputs the results of the query different to reg.exe of Windows Vista and newer Windows versions.
See Microsoft article about Using command redirection operators for an explanation of 2>nul which redirects the error message output by command MD on directory already existing to handle STDERR to the device NUL to suppress this error message.
However, the user's desktop directory should contain only shortcut files (*.lnk files) and the files and directories created by the user on the desktop. No program should create ever other files than shortcut files in the user's desktop directory. Microsoft defined several other shell folders for applications like APPDATA (application data) or LOCALAPPDATA (local application data) for applications.
Some additional facts about handling of string value Desktop under the keys User Shell Folders and Shell Folders by Windows as observed with Windows XP SP3 x86 with always restarting Windows after making a change in registry hive of current user:
A change of the path string of the string value Desktop under the key User Shell Folders for example from %USERPROFILE%\Desktop to %USERPROFILE%\MyDesktop and of course creation of the directory %USERPROFILE%\MyDesktop changes the Windows desktop directory to custom %USERPROFILE%\MyDesktop on next log on and the string value of Desktop under key Shell Folders is adapted by Windows on next restart. It was not tested by me if Desktop under the key Shell Folders is adapted also on just doing a log off and log on. It is definitely better to change both Desktop string values at the same time to change the desktop directory permanently to a directory different from default %USERPROFILE%\Desktop.
A removed or renamed string value Desktop under the key User Shell Folders is never recreated by Windows. So it is possible that this string value does not exist if Desktop under the key User Shell Folders was by mistake once deleted or renamed or the registry file is partly damaged with the result that this string value does not exist. A user would not notice that issue as the further tests below showed.
The string value Desktop of type REG_SZ under key Shell Folders is always set to expanded path of %USERPROFILE%\Desktop if string value Desktop of type REG_EXPAND_SZ under key User Shell Folders does not exist at all. Windows creates also the directory %USERPROFILE%\Desktop automatically if not existing in this error handling case
If the string value Desktop of type REG_SZ under key Shell Folders and the string value Desktop of type REG_EXPAND_SZ under key User Shell Folders are both deleted or renamed by a user or program, Windows creates on next start the string value Desktop of type REG_SZ under key Shell Folders with expanded path of %USERPROFILE%\Desktop and creates also the directory if not existing. The string value Desktop of type REG_EXPAND_SZ under key USer Shell Folders is not recreated by Windows.
If the string value Desktop of type REG_SZ under key Shell Folders exists with a different expanded path than %USERPROFILE%\Desktop like expanded path of %USERPROFILE%\MyDesktop and the string value Desktop of type REG_EXPAND_SZ under the key User Shell Folders does not exit at all, Windows ignores the customized path of Desktop of type REG_SZ under the key Shell Folders and sets the value to expanded path of %USERPROFILE%\Desktop and creates additionally the directory %USERPROFILE%\Desktop if not already existing. So it is not possible to use a customized desktop directory without having the customized desktop directory defined also with string value Desktop of type REG_EXPAND_SZ under the key User Shell Folders.
I did not make tests with newer versions on Windows regarding to handling of Desktop under the keys Shell Folders and User Shell Folders if one or both string values do not exist and/or have same or different directory paths and/or have a directory path different to default.
I would offer a method which retrieves the path from the registry:
#For /F "EOL=HTokens=2*" %%A In ('^""%__AppDir__%Reg.exe" Query^
"HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders"^
/V Desktop^" 2^>NUL')Do #Call MD "%%B\New Directory" 2>NUL
The above is designed to create a directory named New Directory, (change as required), on the current users desktop.
How to search all users' folders and list the files found (with extensions) in an output text file using .bat (cmd) without including data from AppData folders?
Let's say I have user Jenny and user Tommy. And of course within those users there are folders such as desktop, documents, videos, etc.
How can I create a CMD (or PowerShell) script that will search through each users' folders like desktop, documents, videos, etc., BUT prevent the script from pulling results found in the AppData folder.
I was trying to use this code to search each user, but the results were being watered down by what was found in each users AppData folders.
I used %~dp0Files.txt to have the results exported to the desktop where I was executing the .bat from.
cd..
cd..
cd Users
dir /s /p /b >> %~dp0Files.txt
pause
I appreciate any advice. Even if there is a different script file that is better to use for this task.
You could use the command line:
dir "%USERPROFILE%\..\*" /A-D /B /S | %SystemRoot%\System32\findstr.exe /I /L /V /C:"\\AppData\\" >"%USERPROFILE%\Desktop\Files.txt"
The command DIR searches
from parent directory of the current user's profile directory being usually C:\Users on Windows Vista and later Windows versions
for just files because of /A-D (not attribute directory)
recursive in this directory and all subdirectories because of /S and
list them in bare format because of /B which means just the file names with full path.
This output is redirected to FINDSTR which searches in the lines
case-insensitive because of /I and
literally because of /L
for the string \AppData\
and outputs all lines NOT containing this string because of /V (inVerted result).
The backslash character is the escape character in search strings.
Therefore each backslash to find literally must be escaped with one more backslash.
It is possible to specify multiple search strings which are OR combined by using multiple /C:"..." arguments on FINDSTR command line. So it is easily possible to filter out more subdirectories.
The filtered output of FINDSTR is redirected into file Files.txt on desktop of current user always created new on each execution of this command line.
For understanding the two used commands and how they work, open a command prompt window, execute there the following commands, and read entirely the help displayed for each command very carefully.
dir /?
findstr /?
And read the Wikipedia articles about Windows Environment Variables.
Thanks to Mofi's help I was able to also add an exclusion for the All Users folder which was also watering down the results.
My final coded ended up being:
:ScanUsers
#echo off
cls
ECHO Searching users' files
dir "%USERPROFILE%\..\*" /A-D /B /S | %SystemRoot%\System32\findstr.exe /I /L /V /C:"\\AppData\\" >"%~dp0Output\FilesSearch.txt"
start "%~dp0Output\FilesSearch.txt"
wscript.exe "%~dp0Extra\Here is a list of files.vbs"
Timeout 2
goto start
%~dp0Output just directs the text document to be saved into a specific file on the desktop
I've gotten excellent help here recently, which I keenly appreciate. Thanks to the breadth of knowledge on this site I've been able to cobble together some code which is trivial in its purpose, yet important for my environment.
The simplified purpose, and my problem:
The goal: for the current user, upon login to Windows, move all files and folders into a desktop folder named "Archive" [create the latter if necessary]. (The content moved is put into a dynamically created subfolder based on timestamp.)
The existing problem: the code fails to move desktop folders into the (deskstop) Archive folder. (I obviously don't want to move the Archive folder itself.)
Any insight / solution would be hugely helpful. (PS if at all possible I wish to keep to DOS bat files vs more complex languages.)
My current .BAT file [note- the many variables are for initial debugging]:
++++++++++++++++++++++++++++
:: Establish desired base name for the primary desktop archive folder
set ARCH=Archives
:: Establish logged in user path to desktop
set G=%USERPROFILE%\Desktop
:: Now, if "Archives" folder does not yet exist on desktop, create it
if not exist "%G%\Archives" mkdir "%G%\%ARCH%
:: Consolidate pathname <user\desktop\Archives> into single variable (TARGET)
set TARGET=%G%\%ARCH%
:: Create [date+time specific] subfolder name -- two steps - build string, then assign
for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "dt=%%a"
set "YY=%dt:~2,2%" & set "YYYY=%dt:~0,4%" & set "MM=%dt:~4,2%" & set "DD=%dt:~6,2%"
set "HH=%dt:~8,2%" & set "Min=%dt:~10,2%" & set "Sec=%dt:~12,2%" & set "MS=%dt:~15,3%"
:: Set variable to hold new name Archives\Saved-<time-specific-subfolder> in final form
set "savedirname=Saved-%YYYY%-%MM%-%DD%-%HH%-%Min%-%Sec%"
:: Finally, append new foldername to user-specfic path (TARGET)
set MoveTo=%TARGET%\%savedirname%
:: Create final targeted destination folder - complete pathname
mkdir %MoveTo%
:: Move all desktop files/folders EXCEPT the Archives folder into the targeted destination
for %%i in (%G%\*.*) do move %%i %MoveTo%
Thank you!
(PS if at all possible I wish to keep to DOS bat files vs more complex languages.)
This isn't the answer you ask for, but this is PowerShell (v4) code to do what your code does:
$arch = "Archives"
$desktop = [Environment]::GetFolderPath("Desktop")
$saveDirName = Get-Date -f "yyyy-MM-dd-hh-mm-ss"
$target = "$desktop\$arch\$saveDirName"
mkdir $target -Force
dir $desktop | where Name -ne $arch | Move-Item -Destination $target -Force
Is it really "more complex" than your original code?
Your original code guesses that %USERPROFILE%\Desktop is the desktop - that's incorrect if the desktop is redirected, it could be \\fileserver\users\username\desktop\. It's incorrect if the OS is installed in a foreign language, in Swedish it's %UserProfile%\Skrivbord. Asking Windows where the desktop is gets the correct location every time. My code does this.
PowerShell handles dates sanely. No string manipulation, no WMI calls, one formatting string for what format you want.
I use the mkdir -Force option, it can make folders two levels deep in one go, and it does nothing if they already exist. No need for IF NOT EXIST... tests, although you could do them with Test-Path. You could use this approach in the batch file, mkdir can make multiple nested folders there, too.
NB. your code has a bug where you check for "%G%\Archives" but you mkdir "%G%\%ARCH%. If %ARCH% is meant to be configurable, they could differ.
And this version does the folder moving which you are asking about that your code doesn't yet do, and will need another abuse of a for loop to handle.
This script is half the amount of code, more readable because it directly does what it needs instead of wandering out to wmi and string manipulation and for loops for string handling, it's more correct in more situations, more resilient, and does the extra things your original doesn't.
Yes it's a bigger and more complex language - that's how it makes things easier for you, because it can do more things directly.
set fldr="%userprofile%\desktop\archive\%date:/=%%time::=%"
md %fldr%
For /f "delims=" %A in ('dir /a-d /b "%userprofile%\desktop" ^| Findstr /I /v /c:"archive"') Do #echo move "%userprofile%\desktop\%A" %fldr%
The above is all you need.
Batch isn't a programming language, although IBM engineers added programming like features.
It designed for copying files and starting programs. It becomes a stupid language if used as a programming language.
Use %%A in a batchfile. Remove Echo to have it actually move files.
To get the doc folder, which is always called desktop (explorer substitutes localised names for real names via the desktop.ini file)
for /f "skip=2 tokens=3" %A in ('Reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "Personal"') do set doc=%A
Use %%A in a batchfile.
I have a batch file that is in the same directory as the file I want to xcopy. But for some reason the file is not being found.
I thought that current directory was always where the batch file was located.
I run batch file as administrator. This occurs on a Windows 7 64-bit desktop computer.
Batch file:
#ECHO OFF
XCOPY /y "File1.txt" "File2.txt"
PAUSE
Error:
File not found - File1.txt
0 File(s) copied
Which directory is current working directory on starting a batch file with context menu item Run as administrator depends on User Account Control (UAC) setting for the current user.
This can be demonstrated with following small batch file C:\Temp\Test.bat:
#echo Current directory is: %CD%
#pause
With having selected in User Account Control Settings
Default - Notify me only when programs try to make changes to my computer
Don't notify me when I make changes to Windows settings
and using Run as administrator, Windows uses registry key
HKEY_CLASSES_ROOT\batfile\shell\runasuser\command
This registry key does not contain a default string for executing the batch file. Instead there is the string value DelegateExecute with the CLSID {ea72d00e-4960-42fa-ba92-7792a7944c1d}.
The result is opening a dialog window with title User Account Control and text:
Do you want to allow the following program to make changes to this computer?
Program name: Windows Command Processor
Verified publisher: Microsoft Windows
After confirmation by the user, Windows opens temporarily a new user session like when using on command line RunAs.
In this new user session the current working directory is %SystemRoot%\System32 on executing now the command defined in Windows registry with default string of key
HKEY_CLASSES_ROOT\batfile\shell\runas\command
which is:
%SystemRoot%\System32\cmd.exe /C "%1" %*
Therefore a console window is opened with title C:\Windows\System32\cmd.exe and the 2 lines:
Current directory is: C:\Windows\System32
Press any key to continue . . .
After hitting any key, batch execution finishes which results in closing cmd.exe which results in closing the user session.
But with having selected in User Account Control Settings
Never notify me when
Programs try to install software or make changes to my computer
I make changes to Windows settings
the behavior is different as the user has already elevated privileges.
Now Windows uses directly the command
%SystemRoot%\System32\cmd.exe /C "%1" %*
according to default string of key
HKEY_CLASSES_ROOT\batfile\shell\runas\command
in current user session.
The result is opening a console window also with title C:\Windows\System32\cmd.exe, but displayed in window is:
Current directory is: C:\Temp
Press any key to continue . . .
The current working directory of the parent process (Windows Explorer as desktop) is used for executing of the batch file because no switch to a different user session was necessary in this case.
PA has posted already 2 possible solutions in his answer which I replicate here with a small improvement (pushd with directory in double quotes) and with adding a third one.
Change current directory to directory of batch file using pushd and popd:
pushd "%~dp0"
%SystemRoot%\System32\xcopy.exe "File1.txt" "File2.txt" /Y
popd
This works also for UNC paths. Run in a command prompt window pushd /? for an explanation why this also works for UNC paths.
Use directory of batch file in source and destination specifications:
%SystemRoot%\System32\xcopy.exe "%~dp0File1.txt" "%~dp0File2.txt" /Y
Change working directory to directory of batch file using cd:
cd /D "%~dp0"
%SystemRoot%\System32\xcopy.exe "File1.txt" "File2.txt" /Y
This does not work for UNC paths because command interpreter cmd does not support a UNC path as current directory by default, see for example CMD does not support UNC paths as current directories for details.
The error message is very self explanatory. The file file1.txt is not found.
Because the file name does not include an absolute path, the system tries to find it on the current directory. Your current directory does not contain this file.
Your misconception is that the current directory is not the directory that contains the bat file. Those are two unrelated concepts.
You can easily check by adding this two commands in your bat file
echo BAT directory is %~dp0
echo Current directory is %CD%
you can notice they are different, and that there is a subtle difference in the way the last backslash is appended or not.
So, there are esentially two ways to cope with this problem
either change the current directory to match the expected one
pushd %~dp0
XCOPY /y "File1.txt" "File2.txt"
popd
or specify the full path in the command
XCOPY /y "%~dp0File1.txt" "%~dp0File2.txt"
For the sake of completeness and obscurity, I add another workaround, confirmed as working under Windows 8.1 and expected to work elsewhere, as it relies on documented functionality:
You can change the runas command definition keys
HKEY_CLASSES_ROOT\batfile\shell\runas\command and
HKEY_CLASSES_ROOT\cmdfile\shell\runas\command into
%SystemRoot%\System32\cmd.exe /S /C "(for %%G in (%1) do cd /D "%%~dpG") & "%1"" %*
Which results in the bat or cmd file starting in its containing directory when started using the runas verb, respectively the "Run as Administrator" menu entry.
What the additions to the original command exactly do:
cmd /S strips away first and last (double) quote in command string after /C
for %%G in (%1) do enumerates its single entry, the %1 argument,
making it available for expansion as %%G in the loop body; the letter is arbitrary but some may be "reserved"
%%~dpG expands to the drive and path of %%G, the ~ tilde stripping away quotes if present, which is why we add them back explicitly
cd /D changes both the drive and directory to its argument, and finally
& runs the second command "%1" %* regardless of success of the first one.
You can use pushd which will even support UNC paths, but a stray popd would land any script in the system32 directory, not a behavior I would be fond of.
It should be possible to do this for the exefile entry as well, but frankly, I'd rather live with the inconsistency than to attempt this on my system, as any error there could break a lot.
Enjoy defeating the security mechanics of your operating system :)