Getting delayed expansion value to function output - windows

Here is a windows cmd fragment:
:moveFiles
#for /f %%R in ('dir /b current') do (
#echo ___
#echo Moving %%R to FTP server.
%java_cmd% -jar f17ftp.jar -dput -file:%%R %select%
if 1 neq 0 (
#echo Transfer of %%R failed.
call :readLog
echo %log%
%java_cmd% -cp SQLQueryXML.jar com.saliencrgt.chums.AlertMessage "Contents of ftp log are:<br/><br>"%log%
) else (
#echo Transfer of %%R succeeded.
move current\%%R xmlfiles 1> nul
)
)
exit /b
:readLog
setlocal enableextensions enabledelayedexpansion
#for /F "delims=" %%x in (f17ftp.debug.log) do (
if .!build!==. (set build=%%x) else (set build=!build!,%%x)
)
endlocal & set log=!build!
exit /b
I am trying to get the contents of a file into a variable to send as an argument to a java class
The readLog function does read the file and if I echo !build! prior to the endlocal the file contents do print to the console.
I can set "log" to a constant instead of the !build! variable and I see it in the calling function, but I can't get the delayed variable value out of the function.

Here's a quick example of how I'd expect your :readLog labelled section to look:
:readLog
#set "log="
#setlocal enableextensions enabledelayedexpansion
#set "build="
#for /f "usebackq delims=" %%x in ("f17ftp.debug.log") do #(
if not defined build (set "build=%%x") else set "build=!build!,%%x"
)
#endlocal & set "log=%build%"
#exit /b
However to view it, as it is still being defined within a parenthesized block, you will probably find that your :moveFiles labelled section would also need to have enabled delayed expansion, and then echo !log! not echo %log%.
You may find therefore that something a little more like this will work better for you:
:moveFiles
#for /f "eol=? delims=" %%R in ('dir /b "current" 2^>nul') do #(
echo ___
echo Moving %%R to FTP server.
"%java_cmd%" -jar "f17ftp.jar" -dput -file:"%%R" %select%
if errorlevel 1 (
echo Transfer of %%R failed.
setlocal enabledelayedexpansion
set "log="
set "build="
call :readLog
echo !log!
"%java_cmd%" -cp "SQLQueryXML.jar" com.saliencrgt.chums.AlertMessage "Contents of ftp log are:<br/><br>"!log!
endlocal
) else (
echo Transfer of %%R succeeded.
move "current\%%R" "xmlfiles" 1>nul
)
)
#exit /b
:readLog
#for /f "usebackq delims=" %%x in ("f17ftp.debug.log") do #(
if not defined build (set "build=%%x") else set "build=!build!,%%x"
)
#set "log=%build%"
#exit /b

Related

Looping through %1 as a directory in batch?

I've searched the web for answers but can't seem to find an answer. I want the user to provide a directory and to be able to loop through it. I'm able to loop through the current directory like so:
#Echo off
for /r %%f in (*.*) do (
echo %%f
)
But then when I try to do the same by looping through %1, I can't get the result I'm looking for. What am I doing wrong? Here's where I'm at in the batch file:
#Echo off
if exist %1 (
for /r %%f in (%1) do (
echo %%f
)
) else (
echo "That directory does not exist."
)
I've tried using /D but all that did was echo the directory I provided like this:
FileCount C:\Users\Me\Desktop
> C:\Users\Me\Desktop
Edit: My goal for this program is to eventually count the number of files within the given directory. I expect the directory to be provided as it's absolute path and I'll be executing this file through cmd. Here's an example of the input I'm expecting.
FileCount C:\Users\Me\Desktop
And the desired output would be something like:
> Hello world.txt
> Cat.png
> There are 2 files within this directory.
Side-note: I don't want to filter out the output of the dir command, I want to do this with a for loop.
Here's what you asked for, plus the optional recurs feature. Note that this will miss hidden files and directories.
#setlocal EnableExtensions
#prompt=$G
#set _Error_Success=0
#set _Error_PathNotFound=3
#if "%~1" equ "/?" goto :Usage
#if "%~1" equ "" goto :Usage
#if "%~1" equ "/r" (#set _recurs=/r & #set _root=%~2) else (#set _root=%~1)
#if not exist "%_root%" goto :Oops
#set count=0
#pushd "%_root%"
#for %_recurs% %%f in (*) do #call :Counter "%%f"
#popd
#echo There are %count% entries within this directory.
#exit /b %_Error_Success%
:Counter
#set /a count+=1
#echo %~1
#exit /b %_Error_Success%
:Oops
#echo "That directory does not exist."
#exit /b %_Error_PathNotFound%
:Usage
#echo Usage: FileCount [/r] path
And this uses the dir command, without resorting to invoking findstr:
#setlocal EnableExtensions
#prompt=$G
#set _Error_Success=0
#set _Error_PathNotFound=3
#set _Error_InvalidParameter=87
#set _attributes=
#set _recurs=
#set _count=0
#if "%~1" equ "/?" #goto :Usage & #exit
#if "%~1" equ "" goto :Usage
#set _root=%~1
#if not exist "%_root%" goto :Oops
#shift
#pushd "%_root%"
for /f %%G in ('dir /B /A-d %1 %2 %_root%') do #call :Counter "%%G"
#popd
#echo There are %_count% entries within this directory.
#exit /b %_Error_Success%
:Counter
#set /a _count+=1
#echo %~1
#exit /b %_Error_Success%
:HandleOptions
:Oops
#echo "That directory does not exist."
#exit /b %_Error_PathNotFound%
:Usage
#echo Usage: FileCount [/A<Attributes>] [/S] rootPath
#echo Where <Attributes> corresponds to 'dir /A' optiions (see 'help dir')
#echo and /S will cause recursion into subdirectories of rootPath.
This example, uses a for loop, and does not use the dir command, as per your inexplicable request, but it does use xcopy to list and count the files within it instead:
#For %%G In ("%~1") Do #If "%%~aG" Lss "d" (If "%%~aG" GEq "-" (
Echo Error: File argument given, expected a directory.
%SystemRoot%\System32\timeout.exe /T 3 /NoBreak 1> NUL
Exit /B 1) Else (
Echo Error: Invalid argument, directory path expected.
%SystemRoot%\System32\timeout.exe /T 3 /NoBreak 1> NUL
Exit /B 1)
) Else Echo File content of "%~1":& For /F Delims^= %%H In (
'%SystemRoot%\System32\xcopy.exe "%~1" : /HIL') Do #Echo %%~nxH
#%SystemRoot%\System32\timeout.exe /T -1 & Exit /B 0
If you want it to recurse the input directory, then I'd suggest this very small modification:
#For %%G In ("%~1") Do #If "%%~aG" Lss "d" (If "%%~aG" GEq "-" (
Echo Error: File argument given, expected a directory.
%SystemRoot%\System32\timeout.exe /T 3 /NoBreak 1> NUL
Exit /B 1) Else (
Echo Error: Invalid argument, directory path expected.
%SystemRoot%\System32\timeout.exe /T 3 /NoBreak 1> NUL
Exit /B 1)
) Else Echo File content of "%~1":& For /F Delims^= %%H In (
'%SystemRoot%\System32\xcopy.exe "%~1" : /HILS') Do #Echo %%H
#%SystemRoot%\System32\timeout.exe /T -1 & Exit /B 0
Or with a little more work, outputting relative paths instead:
#For %%G In ("%~1") Do #If "%%~aG" Lss "d" (If "%%~aG" GEq "-" (
Echo Error: File argument given, expected a directory.
%SystemRoot%\System32\timeout.exe /T 3 /NoBreak 1> NUL
Exit /B 1) Else (
Echo Error: Invalid argument, directory path expected.
%SystemRoot%\System32\timeout.exe /T 3 /NoBreak 1> NUL
Exit /B 1)
) Else Echo File content of "%~1":& For /F Delims^= %%H In (
'%SystemRoot%\System32\xcopy.exe "%~1" : /HILS') Do #(
Set "}=%%H" & SetLocal EnableDelayedExpansion
For %%I In ("!}:*%~1=.!") Do #EndLocal & Echo %%~I)
#%SystemRoot%\System32\timeout.exe /T -1 & Exit /B 0
setlocal enabledelayedexpansion
rem Put it into a folder that is in ENV PATH variable.
rem So, you can call it from wherever you want.
if not "%~1"=="" (
if exist "%~dpn1" (
set /a "filecount=0"
for /f "tokens=* delims=" %%f in ('dir /b "%~dpn1"') do (
echo %%f
set /a "filecount+=1"
)
echo:
echo In "%~dpn1" found !filecount! file^(s^).
) else (
echo:
echo [ERROR] Invalid input. Please specify:
echo 1. A full path.
echo 2. A folder in cwd.
echo:
echo If input is empty, current working directory (cwd)
echo will be considered.
exit /b 1
)
) else (
set /a "filecount=0"
for /f "tokens=* delims=" %%f in ('dir /b "%~dp0"') do (
echo %%f
set /a "filecount+=1"
)
echo:
echo In "%~dp0" found !filecount! file^(s^).
)
endlocal
If you want it recursive call it as progname.bat /r [foldname]:
setlocal enabledelayedexpansion
rem Put it into a folder that is in ENV PATH variable.
rem So, you can call it from wherever you want.
if "%1"=="/r" shift
if not "%1"=="" (
if exist "%~dpn1" (
set /a "filecount=0"
set /a "totalcount=0"
set "oldroot=%~dpn1"
for /f "tokens=* delims=" %%f in ('dir /b /s "!cd!"') do (
if not "%%~dpf"=="!oldroot!" (
echo:
echo In "!oldroot!" found !filecount! file^(s^).
echo:
set /a "filecount=0"
set "oldroot=%%~dpf"
)
echo --- %%f
set /a "filecount+=1"
set /a "totalcount+=1"
)
echo:
echo In "%~dpn1" found !totalcount! file^(s^).
) else (
echo:
echo [ERROR] Invalid input. Please specify:
echo 1. A full path.
echo 2. A folder in cwd.
echo:
echo If input is empty, current working directory (cwd)
echo will be considered.
exit /b 1
)
) else (
set /a "filecount=0"
set /a "totalcount=0"
set "oldroot=!cd!"
for /f "tokens=* delims=" %%f in ('dir /b /s "!cd!"') do (
if not "%%~dpf"=="!oldroot!" (
echo:
echo In "!oldroot!" found !filecount! file^(s^).
echo:
set /a "filecount=0"
set "oldroot=%%~dpf"
)
echo --- %%f
set /a "filecount+=1"
set /a "totalcount+=1"
)
echo:
echo In "%~dp0" found !totalcount! file^(s^).
)
endlocal
Try it and see if it is what you expected.
Thank you for the help everybody, I've found the solution to the problem and it was very simple. All I needed to do was loop through %1\*.* instead of %1 itself.
#Echo off
if exist %1 (
for %%f in (%1\*.*) do (
echo %%f
)
) else (
echo "That directory does not exist."
)

Use a Batch File to list files and allow the user to select which file to copy into a new destination

I am a newbie to Windows Scripting.
I am trying to list some txt files in several sub directories & want to copy a user selected file to a new destination. Please note that the file name is unique in different locations.
I got the first part to work (Listing out the files & locations) using the following script, but I am unable to copy the selected file to the new location.
#ECHO OFF
SET index=1
SETLOCAL ENABLEDELAYEDEXPANSION
SET FFPath="C:\Scripts - Backup Server\DKXpress_bkp"
SET NewPath=C:\DKServer
ECHO Recursively searching %FFPath%
echo.
FOR /F "delims=" %%f in ('DIR %FFPath%\*.txt /a:-d /s /b') DO (
SET file!index!=%%f
ECHO !index! - %%f
SET /A index=!index!+1
)
SETLOCAL DISABLEDELAYEDEXPANSION
SET /P selection="select file by number:"
SET file%selection% >nul 2>&1
IF ERRORLEVEL 1 (
ECHO invalid number selected
EXIT /B 1
)
SET NewFile=file%selection%
ECHO Copying %NewFile% to %NewPath%
ECHO.
COPY /Y "%NewFile%" "%NewPath%"
ECHO.
PAUSE
I think I am doing this part wrong
SET NewFile=file%selection%
Thank you all in advance
You don't need to set an index variable or delayed expansion, if you let Find do the work for you:
#Echo Off
Set "FFPath=C:\Scripts - Backup Server\DKXpress_bkp"
Set "NewPath=C:\DKServer"
Echo Recursively searching %FFPath%
Echo=
For /F "Delims==" %%A In ('"Set File[ 2>Nul"') Do Set "%%A="
For /F "Tokens=1* Delims=]" %%A In (
'"Dir /B/S/A-D-S-L "%FFPath%\*.txt" 2>Nul|Find /N /V """') Do (
Echo %%A] %%B
Set "File%%A]=%%B"
)
Echo=
Set /P "#=Select file by number: "
Echo=
For /F "Tokens=1* Delims==" %%A In ('"Set File[%#%] 2>Nul"') Do (
Echo Copying %%B to %NewPath%&Echo=
Copy /Y "%%B" "%NewPath%"
GoTo :End
)
Echo Invalid number selected
:End
Echo=
Pause
You need to use delayed expansion to get the file name assigned to the variable correctly.
SET NewFile=!file%selection%!
Remove the setlocal to disable delayed expansion.
You can try something like that :
#ECHO OFF
:Main
cls
SET index=1
SETLOCAL ENABLEDELAYEDEXPANSION
SET FFPath="C:\Scripts - Backup Server\DKXpress_bkp"
SET "NewPath=C:\DKServer"
ECHO Recursively searching %FFPath%
echo.
FOR /F "delims=" %%f in ('DIR %FFPath%\*.txt /a:-d /s /b') DO (
SET filepath[!index!]=%%f
ECHO [!index!] - %%~nxf - %%f
SET /A index=!index!+1
)
echo(
echo select file by number :
set /p Input=""
For /L %%i in (1,1,%index%) Do (
If "%INPUT%" EQU "%%i" (
ECHO Copying "!filepath[%%i]!" to "!NewPath!"
COPY /Y "!filepath[%%i]!" "!NewPath!"
)
)
echo Copying another file ? (Y = Yes or N = No) ?
set /p input2=""
If /I "!input2!"=="Y" (
goto :Main
) else (
goto :eof
)

How to create a unique output filename for Windows Script?

I am trying to create a windows script that should generate this kind of filename everytime I run it: filename1, filename2, filename3 and so on. Here is what I have so far:
(
#echo off
wmic logicaldisk get size,freespace,caption
) > disk.txt
I hope you can help me. Thanks!!
:: make a tempfile
:maketemp
SET "tempfile=%temp%\%random%"
IF EXIST "%tempfile%*" (GOTO maketemp) ELSE (ECHO.>"%tempfile%a")
You now have any number of filenames available.
%tempfile%a exists and is empty, but %tempfile%anythingelse should be available for use.
#ECHO OFF
SETLOCAL
SET "basename=filename"
SET /a outname=0
:genloop
SET /a outname+=1
IF EXIST "%basename% %outname%.txt" GOTO genloop
SET "outname=%basename% %outname%.txt"
ECHO %outname%
GOTO :EOF
Ah - increment the destination filename on each run. This should do that. It's not actually creating a file - you'd need to create the file %outname% each time to have it increment...
(the space between %basename% and %outname% is optional, of course - omit it if desired.)
edited to include .txt
This will give you up to 1000 filenames but you can go higher, up to 2 Billion, but the higher you go the longer the delay will be before it picks a filename.
#echo off
for /L %%a in (1,1,1000) do if not defined filename if not exist "filename%%a.txt" set "filename=filename%%a.txt"
(
wmic logicaldisk get size,freespace,caption
) > "%filename%"
#echo off
setlocal enableextensions
call :getNextFilename "filename*.txt" nextFilename
echo %nextFilename%
echo test > "%nextFilename%"
call :getNextFilename "%cd%\filename*.txt" nextFilename
echo %nextFilename%
echo test > "%nextFilename%"
endlocal
exit /b
:getNextFilename whatToSearch returnVariable
setlocal enableextensions enabledelayedexpansion
for /f %%a in ("$\%~1"
) do for /f "tokens=1,* delims=*" %%b in ("%%~nxa"
) do ( set "left=%%b" & set "right=%%c" )
set "max=0"
for %%a in ("%~1"
) do for /f "tokens=1 delims=%left%%right% " %%b in ("%%~nxa"
) do for /f "tokens=* delims=0 " %%c in ("0%%~b"
) do if %%~c geq !max! set /a "max=%%c+1"
endlocal & set "%~2=%~dp1%left%%max%%right%" & exit /b
This should find the next file in sequence independently of the existence of holes in the numeration of the files. A path can be included or omitted. The * will be used as the placeholder for the numeration. BUT this will not work if files or included paths have "problematic" characters.
If the date/time of creation of the file can be considered, then this version can be optimized as
:getNextFilename whatToSearch returnVariable
setlocal enableextensions disabledelayedexpansion
for /f %%a in ("$\%~1"
) do for /f "tokens=1,* delims=*?" %%b in ("%%~nxa"
) do ( set "left=%%b" & set "right=%%c" )
set "max=0"
for /f "delims=" %%a in ('dir /tc /o-d /b "%~1" 2^>nul'
) do for /f "tokens=1 delims=%left%%right% " %%b in ("%%~nxa"
) do for /f "tokens=* delims=0 " %%c in ("0%%~b"
) do set /a "max=%%c+1" & goto done
:done
endlocal & set "%~2=%~dp1%left%%max%%right%" & exit /b
that will take the latest created instance of the file set.
I finally figured out where to put the .txt extension. This is from #Magoo's answer but I wanted the file to be a text file so I placed the .txt twice in order for it to work properly.
#ECHO OFF
SETLOCAL
SET "basename=DISK-OUT"
SET /a outname=0
:genloop
SET /a outname+=1
IF EXIST "%basename% %outname%.txt" GOTO genloop
SET "outname=%basename% %outname%.txt"
(
wmic logicaldisk get size,freespace,caption
) > "%outname%"
GOTO :EOF

for command is executed only for the first value when a label is inside

I have the script
for /f "delims=" %%i in ('dir "%folder%*.txt" /b /s') do (
set s=%%i
set s=!s:%folder%=!
set new_s=!s:\=!
if "x!new_s!" NEQ "x!s!" (
:ProcessListSource
For /f "tokens=1* delims=\" %%A in ("!s!") do (
if "%%A" NEQ "" (
if "!Folder1!" NEQ "" (
Set Folder1=!Folder1!\!Name!
)else (
Set Folder1=!Name!
)
Set Name=%%A
)
if "%%B" NEQ "" (
set s=%%B
goto :ProcessListSource
)
)
echo Folder is: !Folder1!
echo Name is: !Name!
echo ---------------------
) else (
echo Not a folder !s!
)
)
but it does not work as I would have expected:
The first for is executed only once and also the last echo is printed on the screen.
Given a folder I need the files from subfolders without the given folder and than split them into the folder and file
Ex: folder=C:\test
The for would give me the file C:\test\test1\test2\t.txt
And I need test1\test2 and t.txt
GOTO breaks your FOR /F \ IF context and they can be executed only once.
More simple example:
#echo off
for /l %%S in (1=1=5) do (
echo %%S
goto :inner_label
rem
:inner_label
rem
)
This will print only 1 . Do you really need the GOTO here?
When the parser reads your code, all the code inside your for loop is "considered" as only one command that is readed, parsed and executed. As stated in the npocmaka answer, any goto call takes you out of this "line" of code, ending the process of the for loop.
This is a alternative. Use pushd + xcopy /l /s commands to generate a list of the relative paths of the files.
#echo off
setlocal enableextensions disabledelayedexpansion
set "folder=%cd%"
pushd "%folder%"
for /f "delims=" %%a in ('xcopy /l /s /y * "%temp%"^|findstr /vbr /c:"[0-9]"'
) do for /f "delims=: tokens=1,*" %%b in ("%%~a") do (
echo [%%c] [%%~nxa]
)
popd

set nor working inside a for loop for windows dos cmd

I have a script that eill search for certain directories and set a list of paths for the given directories, now i want to exclude from them some recurrent unwanted ones.
Here's the script
#ECHO off
setlocal enableextensions
:start
set scriptname=%0%
set PAUSE_ON_ERROR=yes
rem #
rem ###### SECTION TO CUSTOMIZE #####
rem #
rem #
rem # This is the list of directories where instances of TECSYS iTopia installed under
rem # JBoss are located.
rem #
set jboss_dir_list=C: C:\TecsysDev\iTopiaControlPanel\trunk
rem #
rem ###### END SECTION TO CUSTOMIZE #####
rem #
set argNb=0
for %%x in (%*) do Set /A argNb+=1
if %argNb% GTR 1 (
goto :showUsage
) else if %argNb% == 0 (
set ENV_NAME=*
) else (
set ENV_NAME=*%~1*
)
:MainBlock
set scriptname=%0%
cd /d %~dp0
for /f "usebackq delims=" %%D in (`cd`) do set scriptdir=%%D
for /f "usebackq delims=" %%D in (`cd`) do set CURRENT_DIR=%%D
cd "%scriptdir%"
for /f "usebackq delims=" %%D in (`cd`) do set JBOSS_DIR=%%D
set JBOSS_DIR=%JBOSS_DIR%\..\..\..\..\..
cd "%JBOSS_DIR%"
for /f "usebackq delims=" %%D in (`cd`) do set JBOSS_DIR=%%D
cd "%CURRENT_DIR%"
rem Make sure that we have the findstr utility installed.
set findstr_found=
for /f "usebackq" %%f in (`echo x ^| findstr x 2^>nul`) do set findstr_found=%%f
if "X%findstr_found%" == "X" (
echo The findstr utility is not found.
goto pauseforError
)
call :getJbossVersion
rem prepare the list of special JBoss environments to exclude
if /i "%JBOSS_VERSION%" lss "5" (
set env_to_exclude=all default minimal
) else if /i "%JBOSS_VERSION%" lss "6" (
set env_to_exclude=all default minimal standard web
) else (
set env_to_exclude=all default minimal jbossweb-standalone standard
)
rem find the environment directories
setlocal enabledelayedexpansion
Set Count=1
for %%f in (%jboss_dir_list%) do (
for /f "delims=" %%G in ('dir /b /ad "%%~f\jboss*"') do (
if exist "%%f\%%G\server\%ENV_NAME%" (
for /f "delims=" %%H in ('dir /b /ad "%%~f\%%~G\server\%ENV_NAME%"') do (
echo count est !count!
call :concat %%~f\%%~G\server\%%~H
Set /A Count+=1
)
)
)
)
rem echo %ENV_NAME%
rem %jboss_home_list%
:concat
echo the environment is %1
set is_env_to_exclude=no
for %%L in (%env_to_exclude%) do (
set is_env_to_exclude=no
for /f "usebackq delims=" %%U in (`echo %1 ^| findstr %%L`) do (
set is_env_to_exclude=yes
echo flag du Ellouze
)
)
echo %is_env_to_exclude%
rem echo %is_env_to_exclude%
rem set jboss_home_list=%1 %jboss_home_list%
goto :eof
:getJbossVersion
for /f "usebackq tokens=2" %%v in (`echo. ^| %JBOSS_DIR%\bin\run.bat -V ^| ^
findstr "JBoss" ^| findstr /i /v "BootStrap"`) do (
set JBOSS_VERSION=%%v
)
goto :EOF
:showUsage
echo Usage: tish [environment]
echo ^|
echo +--- installed environment
rem SET /P uname=Please enter your name:
rem IF "%uname%"=="" GOTO Error
rem ECHO Hello %uname%, Welcome to DOS inputs!
rem GOTO End
rem :Error
rem ECHO You did not enter your name! Bye bye!!
:pauseforError
if "%PAUSE_ON_ERROR%" == "yes" pause
:End
My idea is to to do the filetring through the :concat subroutine, problem is set is_env_to_exclude=yes insrtuction inside the for loop isn't working, when i execute the script the echo flag is displaying but the set is_env_to_exclude is always set to no.
I think what you need is to break the loop:
echo the environment is %1
set is_env_to_exclude=no
for %%L in (%env_to_exclude%) do (
set is_env_to_exclude=no
for /f "usebackq delims=" %%U in (`echo %1 ^| findstr %%L`) do (
set is_env_to_exclude=yes
echo flag du Ellouze
goto :break_loop
)
)
:break_loop
echo %is_env_to_exclude%
as on each iteration over %env_to_exclude% items the is_env_to_exclude is set to no.
Although the code is a little bit complicated for me :)
It really depends on the contents of env_to_exclude.
is_env_to_exclude will be set to no for each %%L, so even if it is set to yes once, if there are more elements processed after it's been set, it will be re-set to no.
The
set is_env_to_exclude=no
in the loop seems to be the culprit; removing it would seem to fix the problem.
AAMOI, set "flag=" and set flag=Y allows if [not] defined flag which has the added advantage that the CURRENT status of the flag is available within a FOR loop without needing enabledelayedexpansion.

Resources