Can you set a File's (A music file's Contributing Artists) MetaData as a varible?

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
Fighting_monster
Posts: 1
Joined: 29 Apr 2017 19:30

Can you set a File's (A music file's Contributing Artists) MetaData as a varible?

#1 Post by Fighting_monster » 29 Apr 2017 19:38

Okay, I am making a batch file to take a chunk of music and then put them in files according to artists. I am having trouble with finding out a way to take the file's Contributing Art Metadata Value to set the file's ,the one it is going into, name.
Is there a single command I am missing or is it impossible or is it just this long complicated problem. Sorry for the stupid question :oops: .

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Can you set a File's (A music file's Contributing Artists) MetaData as a varible?

#2 Post by aGerman » 30 Apr 2017 06:50

You can't using pure batch. It's possible with a hybrid script.

Save with extension .bat :

Code: Select all

@if (@a)==(@b) @end /*

:: Batch
@echo off &setlocal
set "property=Contributing Artists"

for %%i in (*.mp3) do (
  for /f "delims=" %%j in ('cscript //nologo //e:jscript "%~fs0" "%%~i" "%property%"') do echo %%j --- "%%~i"
)
pause

:: JScript
exit /b&::*/ try {
  var objFSO = WScript.CreateObject('Scripting.FileSystemObject'), objWShell = WScript.CreateObject('WScript.Shell'),
      objShell = WScript.CreateObject('Shell.Application');
  objWShell.CurrentDirectory = objFSO.GetParentFolderName(WScript.ScriptFullName);
  var strFullName = objFSO.GetAbsolutePathName(WScript.Arguments(0)), objFolder = objShell.Namespace(objFSO.GetParentFolderName(strFullName)),
      objFolderItem = objFolder.ParseName(objFSO.GetFileName(strFullName)), i = 0, strPropName = '';
  while ((strPropName = objFolder.GetDetailsOf(null, i)) != '') {
    if (strPropName.toLowerCase() == WScript.Arguments(1).toLowerCase()) {
      WScript.StdOut.WriteLine(objFolder.GetDetailsOf(objFolderItem, i));
      WScript.Quit(0);
    }
    i++;
  }
}
catch(e) {
  WScript.StdErr.WriteLine(e.message);
  WScript.Quit(1);
}


The code lists all .mp3 files in the current directory together with their Contributing Artists properties. Files without this property are left out.
NOTE: The property name is language-dependent. E.g. in Germany I have to replace "Contributing Artists" with "Mitwirkende Interpreten". Find the right name in the "Details" tab of the file properties.

Steffen

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Can you set a File's (A music file's Contributing Artists) MetaData as a varible?

#3 Post by aGerman » 30 Apr 2017 11:03

Fighting_monster asked me via PM to explain the code a little. Comments added:

Code: Select all

@if (@a)==(@b) @end /* ::Harmless hybrid line that is valid in both Batch and JScript. It introduces a JScript multiline comment in order to skip the Batch code.

:: Batch
@echo off &setlocal
REM Name of the properyou want to determine.
set "property=Mitwirkende Interpreten"

REM Get all .mp3 file names in the current directory and save them in %%i step by step for each loop iteration
for %%i in (*.mp3) do (
  REM Execute this script file as JScript, pass the current mp3 file name in %%i and the property name you want to get.
  REM Process the output of the JScript in a FOR /F loop in order to catch it into variable %%j.
  REM Output both property and mp3 file name
  for /f "delims=" %%j in ('cscript //nologo //e:jscript "%~fs0" "%%~i" "%property%"') do echo %%j --- "%%~i"
)
REM Suspend batch execution to keep the window open.
pause

:: JScript
REM Quit the batch execution, end the JScript comment block, begin the JScrip "try" block
exit /b&::*/ try {
  /* Create scripting objects that provide methods to for several needed tasks */
  var objFSO = WScript.CreateObject('Scripting.FileSystemObject'), objWShell = WScript.CreateObject('WScript.Shell'),
      objShell = WScript.CreateObject('Shell.Application');
  /* Make sure the working directory of the JScript is the same as the directory of the script file */
  objWShell.CurrentDirectory = objFSO.GetParentFolderName(WScript.ScriptFullName);
  /* Get the full path of the passed file name, get the shell folder object where the passed file was saved, ... */
  var strFullName = objFSO.GetAbsolutePathName(WScript.Arguments(0)), objFolder = objShell.Namespace(objFSO.GetParentFolderName(strFullName)),
      /* ... get the folder item object of the passed file, initialize index i with 0 and the proprty name with an empty string */
      objFolderItem = objFolder.ParseName(objFSO.GetFileName(strFullName)), i = 0, strPropName = '';
  /* Run a loop as long as property names where found. Assign the found property name to variable strPropName */
  while ((strPropName = objFolder.GetDetailsOf(null, i)) != '') {
    /* Compare the found property name with the property name passed to the script, if equal ... */
    if (strPropName.toLowerCase() == WScript.Arguments(1).toLowerCase()) {
      /* ... output the property value and quit the JScript execution with errorlevel 0. */
      WScript.StdOut.WriteLine(objFolder.GetDetailsOf(objFolderItem, i));
      WScript.Quit(0);
    }
    /* Increment index i for the next loop iteration */
    i++;
  }
}
/* If an error occurred ... */
catch(e) {
  /* ... output the error message and quit the JScript execution with errorlevel 1. */
  WScript.StdErr.WriteLine(e.message);
  WScript.Quit(1);
}


Everything after EXIT /B was never seen by the command line processor.
Everything between /* and */ is a comment in JScript and will be ignored during JScript execution.
This way the same script file can be executed twice - as Batch and as JScript.

For more information search the site for JScript hybrids.

Steffen

Post Reply