How do I set the working directory of a batch script to where the shortcut is invoked? - batch-file

I have a simple batch script that copies the contents of ./source to a destination specified as an argument. Once the files in ./source are copied to the destination, they are moved to ./archive.
script.cmd "\\web01\www\accounting\assets" "otherArgs"
This script is going to be used to in several areas, but instead of having discrete copies of the script in each area it is being used, I want to utilize shortcuts(.lnk) to point back to one copy of the script, so that if changes are made everyone using it is using the most up-to-date version.
The folder structure would look something like this:
company
|
+-- script.cmd
|
+-- accounting
| |
| +-- archive
| | |
| | \-- oldFile
| |
| +-- source
| | |
| | \-- newFile
| |
| \-- script.lnk -> ..\script.cmd
|
+-- hr
| |
| +-- archive
| | |
| | \-- oldFile
| |
| +-- source
| | |
| | \-- newFile
| |
| \-- script.lnk -> ..\script.cmd
|
+-- sales
| |
| +-- archive
| | |
| | \-- oldFile
| |
| +-- source
| | |
| | \-- newFile
| |
| \-- script.lnk -> ..\script.cmd
|
...
Currently, the script is not using the correct archive and source directories. It is trying to look for the directories at the top level, not in the subdirectories. Is there a variable like %~dp0 or %cd% that would have the path where the shortcut resides? Or is there a way I can pass it in as an argument without using an absolute path? Such as
script.cmd "\\web01\www\accounting\assets" "%cd%" "otherArgs"

Use an alias script:
#setlocal ENABLEEXTENSIONS
#cd %~dp0
call %path_to_script%\script.cmd %*
Put one of those in each of your directories. No shortcuts required.

Related

Move files with all subdirectories

I want to move all files and directories to another specific directory.
|
\---MainDirectory
| MainFiles
|
+---Subdirectory1
| MultipleFiles1
|
\---Subdirectory2
MultipleFiles2
|
\---TargetDirectory
| MainFiles
|
+---Subdirectory1
| MultipleFiles1
|
\---Subdirectory2
MultipleFiles2
Currently using following code with batch file:
move "MainDirectory" "TargetDirectory"
It is moving only MainDirectory like:
|
\---TargetDirectory
MainFiles
I do not want to move MainDirectory. I know it is very basic question, but I am not expert and have searched for more than 2 hours and haven't found a solution.
I tried
robocopy "MainDirectory" "TargetDirectory" /MOVE
It is also moving only MainFiles.
This code is moving successfully but removing MainDirectory which I do not want to remove
robocopy.exe "MainDirectory" "TargetDirectory" /S /Move

Convert to another folder

This command works for me:
To run from cmd.exe:
convert *.jpg -set filename:f "%t.%e" "%[filename:f].png"
The same, to run from bat-file (double % instead of single):
convert *.jpg -set filename:f "%%t.%%e" "%%[filename:f].png"
Now, let's assume I have this file hierarchy:
test\
|-- small\ <-- this is an empty folder
|-- image1.jpg
|-- image2.jpg
How I should modify existing script to output files in small folder, as shown below?
Current behaviour:
test\
|-- small\
|-- image1.jpg
|-- image2.jpg
|-- image1.jpg.png
|-- image2.jpg.png
Desired behaviour:
test\
|-- small\
|-- image1.jpg.png
|-- image2.jpg.png
|-- image1.jpg
|-- image2.jpg
I tried to use %~dp0, but with no luck currently.
I think I understand, but make a backup before trying:
mogrify -path small -format png *.jpg
I don't have Windows readily available to test, but in the light of your comments try:
convert *.jpg -set filename:f "%%t.%%e" "small/%%[filename:f].png"

Windows Batch : list all files with name, path, data modified, date created and owner into a csv file or txt file

I have a script that can display the file path, there are some properties that can not be displayed, such as date modified, date create, owner.
#ECHO off
SET v1=%%~dpF
SET v2=%%~nxF
(for /r %%F in (*) do #echo "%v1%","%v2%"
pause
Example Output :
- D:/newfolder1/tester.doc | 18/02/2016 01:30:00 | 16/02/2016 02:13:12 | Nickolas
- D:/newfolder2/tester2.doc | 11/03/2016 01:30:00 | 12/02/2016 02:13:12 | Marx Timberlack
- D:/newfolder3/tester3.doc | 18/02/2016 01:30:00 | 16/02/2016 02:13:12 | Administrators
Basically I want to add a 4th parameter, which should show file owner. It is in Windows 7 environment.
As mentioned in a comment by Klitos Kyriacou, PowerShell can do this:
PARAM (
$Path = 'C:\Users\MarxHood\Desktop\', $Report = 'C:\Users\MarxHood\Output.csv'
)
$Owner = #{
Name = 'FileOwner'
Expression = { ((Get-Acl $_.FullName).Owner).Split('\')[1] }
}
Get-ChildItem -Path $Path -Recurse | Select FullName, LastWriteTime, CreationTime, $Owner | Export-Csv -NoTypeInformation -Delimiter "|" $Report
Just change the locations as necessary for $Path and $Report at the top.
Edit
Below is a method using a batch file, unfortunately this is dependent upon the localised date/time output; (tokens may need adjusting to suit your locale). Domain names in the owner output string which contain a space would also cause this to fail.
#Echo Off
Set "Path=C:\Users\MarxHood\Desktop"
Set "Report=C:\Users\MarxHood\Output.csv"
(For /F "EOL= Tokens=1,2,4*" %%A In ('Dir/A-D/-C/Q/TC "%Path%\*"'
) Do For /F "Delims=" %%E In ("%%~tD"
) Do Echo="%%~fD"^|"%%E"^|"%%A %%B"^|"%%~nC")>"%Report%"
Remember to change the locations as necessary for %Path% and %Report% near the top.
Using the command dir /TC will show you the creation date of each file. /TA will show you last-access, and /TW will show last-written.

How to load files according to Created Date in Windows command shell via SQL Server's xp_cmdshell

In SQL Server, I am using a query below to load all ".jpg" file names from a specific directory (e.g. z:) into a table.
I want to know if there's a way to load files according to Created Date instead of Modified Date in Windows command prompt. The query below only works with Modified Date when executing xp_cmdshell.
-- Create the table to store file list
CREATE TABLE myFilesTable (myFileID INT IDENTITY, myFileName NVARCHAR(256))
-- Insert file list from directory to SQL Server
DECLARE #Command varchar(1024) = 'z: & forfiles /m *.jpg /s /d 07/16/2015 /c "cmd /c echo #fdate #ftime #path"'
INSERT INTO myFilesTable
EXEC MASTER.dbo.xp_cmdshell #Command
-- Check the list
SELECT * FROM myFilesTable
GO
07/16/2015 in the variable #Command is the Modified Date. Obviously the command forfiles doesn't have a clue to filter files by Created Date.
Below is a few results from the query given above in which FileNames are prefixed by Modified Date.
myFileID | myFileName
----------------------
1 | NULL
2 | 8/18/2015 11:13:08 AM "Z:\LDB1 App Export\Top Star_Aluminium Frames & Furniture (B)-31267.jpg"
3 | 8/19/2015 5:44:41 PM "Z:\LDB2 App Export\Soe Tint_Hardware Merchants & Ironmongers-31435.jpg"
4 | 8/19/2015 10:37:13 AM "Z:\Cover App Export\Taw Win Tun_Electrical Goods Sales & Repairing (A) -31382.jpg"
5 | 8/24/2015 10:34:33 AM "Z:\CP1 App Export\Thiri May_Fabric Shop (B)-30646.jpg"
6 | 8/17/2015 10:08:39 AM "Z:\CP2 App Export\Ko Tin Aung_Building Materials (B)-31300.jpg"
I have also tried using dir command with timefield /t:c (the creation time) something like
EXEC MASTER.dbo.xp_cmdshell 'dir z: *.jpg /t:c /s'
It gives me the Created Date but it shows me the following result which is not as expected. I want the file names with full path/directory names as shown in the previous result.
myFileID | myFileName
----------------------
1 | Volume in drive Z is Publication
2 | Volume Serial Number is 3EF0-5CE4
3 | NULL
4 | Directory of Z:\
5 | NULL
6 | 07/28/2015 06:41 PM <DIR> .
7 | 07/28/2015 07:06 PM <DIR> ..
8 | 03/05/2015 11:42 AM <DIR> LDB1 App Export
9 | 03/05/2015 05:31 PM <DIR> LDB2 App Export
10 | 0 File(s) 0 bytes
11 | NULL
12 | Directory of Z:\LDB1 App Export
13 | NULL
14 | 03/05/2015 11:42 AM <DIR> .
15 | 07/28/2015 06:41 PM <DIR> ..
16 | 07/28/2015 06:49 PM 2,981,526 Kyaw Phay_Dental Equipment (A)-30998.jpg
17 | 08/31/2015 03:10 PM 3,126,629 Venus_Fashion Shops-31438.jpg
18 | 07/28/2015 06:49 PM 3,544,247 Marvellous_Tourism Services-30986.jpg
... | ...
The expected result should be something like below,
myFileID | CreatedDate | myFileName
----------------------------------------------
1 | 8/10/2015 11:24:16 AM | "Z:\LDB1 App Export\Top Star_Aluminium Frames & Furniture (B)-31267.jpg"
2 | 8/10/2015 11:24:27 AM | "Z:\LDB2 App Export\Soe Tint_Hardware Merchants & Ironmongers-31435.jpg"
3 | 8/12/2015 10:05:22 AM | "Z:\Cover App Export\Taw Win Tun_Electrical Goods Sales & Repairing (A) -31382.jpg"
4 | 8/12/2015 10:05:22 AM | "Z:\CP1 App Export\Thiri May_Fabric Shop (B)-30646.jpg"
5 | 8/12/2015 10:05:22 AM | "Z:\CP2 App Export\Ko Tin Aung_Building Materials (B)-31300.jpg"
Any help would be very appreciated :)
Here is one way you can parse the output of the DIR command:
--Create the table to store file list
CREATE TABLE myFilesTable (myFileID INT IDENTITY, myFileCreateDate datetime, myFileName NVARCHAR(256))
--Create temporary table to store output of DIR command
CREATE TABLE #DirectoryOutput (LineID INT IDENTITY, LineData NVARCHAR(256))
--Insert file list from directory to SQL Server
DECLARE #Command varchar(1024) = 'dir z: *.jpg /t:c /s'
INSERT INTO #DirectoryOutput
EXEC MASTER.dbo.xp_cmdshell #Command
--Check the list
insert into myFilesTable
select
convert(Datetime,(left(LineData, 20))) CreateDate,
FilePath2.FilePath + '\' + right(LineData,len(LineData)-39) Filename
from #DirectoryOutput
cross apply
(
select Max(LineID) LineID
from #DirectoryOutput FilePaths
where LEFT(LineData,14)=' Directory of '
and FilePaths.LineID < #DirectoryOutput.LineID
) FilePath1
join
(
select LineID, RIGHT(LineData, LEN(LineData)-14) FilePath
from #DirectoryOutput FilePaths
where LEFT(LineData,14)=' Directory of '
) FilePath2
on FilePath1.LineID = FilePath2.LineID
where ISDATE(left(LineData, 20))=1
order by 1
select * from myFilesTable
GO
I slightly changed your table to include a separate column for the creation date:
CREATE TABLE myFilesTable ( myFileID int IDENTITY
, myFileName nvarchar(256)
, myFileCreationDate datetime
)
You can use following PowerShell script to get the directory information and write it to the SQL table:
Import-Module "C:\Program Files (x86)\Microsoft SQL Server\110\Tools\PowerShell\Modules\SQLPS" -DisableNameChecking
$files = Get-ChildItem "z:\" -Filter "*.jpg" -recurse | Where-Object { $_.CreationTime -ge "07/16/2015" } | Select-Object FullName, CreationTime
foreach ($file in $files)
{
$creationTime = $file.CreationTime -f "dd-MM-yyyy hh:mm:ss"
$file.FullName = $file.FullName -replace "'", "''"
Invoke-Sqlcmd -ServerInstance "YourInstance" `
-Database "YourDatabase" `
-Query ("INSERT INTO {0} (myFileName, myFileCreationDate) VALUES ('{1}', '{2}')" `
-f "myFilesTable", $file.FullName, $creationTime)
}
Replace the YourInstance value with your instance name and the YourDatabase value with the name of your database.
I strongly advise against using xp_cmdshell as it open a windows command shell with the same security context as the SQL server service account. This is a security risk and it is best is to disable the xp_cmdshell command.
You can best execute the PowerShell command on the SQL Server. Prerequisite is that the SQLPS module is available (for the Invoke-SqlCmd commandlet). This prerequisite is met when you have installed SQL Server.
EDIT:
So if you really want to do it via xp_cmdshell, you can save the PowerShell script on your SQL Server and execute it the following way (I modified the path to the SQLPS file in the PowerShell script, assuming you have SQL Server 2012):
EXEC xp_cmdshell 'powershell.exe -file "C:\FileList.ps1" -ExecutionPolicy Unrestricted'
Where C:\FileList.ps1 is your saved PowerShell script.
forfiles only offers the modified date filter (see docs). Instead you can execute PowerShell from within SQL (e.g. like this) and since PowerShell has lots of nice filters it'll be easy to do that based on Created Date (e.g. like this).
If you change your #Command to
DECLARE #Command varchar(1024) = '#echo off
For /f "tokens=1-6 delims= " %%a in (''dir *.png /t:c /o:d'') do ( if exist %%e ( echo %%a %CD%%%e ))'
The #echo off ensures that the commands are not displayed and this line must be on a separate line.
I escaped the single quotes in SQL by replacing ' with '' (2 single quotes not a double quote).
The dos command produces the following output:
Date FileNameWithPath
07/15/2015 [Drive]:\[Path]\image.jpg
I hope this helps you get closer to what you need.

In cmd how can I list folders that contain files with a specific extension?

Using just the command prompt or a batch script, I would like to look inside my current directory and all subdirectories for folders containing a specific filetype.
So, example:
Say I am in directory F:\dir\one\, and F:\dir\one\ looks like this:
F:\dir\one\
|
+--F:\dir\one\two\
| |
| +--file.c
|
+--F:\dir\one\three\
| |
| +--work.py
| |
| +--F:\dir\one\three\four\
| | |
| | +--file2.c
And I ran my command/script looking for *.c files, I would expect an output of
>F:\dir\one\two
>F:\dir\one\three\four
because those folders contain *.c files.
How could I do this?
To be run from command line. For batch files, percent signs need to be escaped, replacing % with %%
for /r %a in (.) do #if exist "%~fa\*.c" echo %~fa
This:
for /r %a in (.) do #if exist "%~fa*.c" echo %~fa
works for current directory but it doesn't if you specify in which directory you would like to have result:
for /r %a in ('F:\dir\one') do #if exist "%~fa*.c" echo %~fa
it just hangs. I tried 'F:\dir\one' and "F:\dir\one" and 'F:\dir\one\' and "F:\dir\one\"

Resources