Копирование файла, а не ярлыка?

Обсуждение вопросов автоматизации Total Commander с помощью сторонних программ и скриптовых технологий.

Модераторы: d-view, Моторокер, Avada, CaptainFlint, Nik

DjDf
Сообщения: 24
Зарегистрирован: Вт май 03, 2005 12:51

Копирование файла, а не ярлыка?

Сообщение DjDf »

Подскажите, кто знает, решение...

Проблема: в одном месте на диске хранятся файлы. Во втором - выборочные ярлыки на эти файлы. Как переписать, положим на флэшку или еще куда именно файлы, а не ярлыки?

Спасибо!
Аватара пользователя
Parcan
Сообщения: 399
Зарегистрирован: Ср дек 15, 2004 16:39
Откуда: Russian

Сообщение Parcan »

DjDf
может тебе попробовать плагин FileRedirector только придется все файлы на которые созданы ярлыки послать в него, но зато потом ты получишь то, что тебе надо, а если тебе это надо часто, то это самое то.
Аватара пользователя
Batya
Сообщения: 2236
Зарегистрирован: Ср дек 15, 2004 09:51
Откуда: Москва, Россия

Сообщение Batya »

DjDf
Специально для тебя написал небольшой скриптик:

Код: Выделить всё

'==========================================================================
' Копирование файлов (в т.ч. файлов из ярлыков) из одной панели TC в другую
'
' В параметрах вызова из TC должно быть прописано:
' %L
'====================================================================

Dim TempFile, TCS, MyShell, FSO
Set TempFile = CreateObject("Scripting.FileSystemObject").OpenTextFile(WScript.Arguments(0), 1)
Set TCS = CreateObject("TCScript.Helper")
Set MyShell = WScript.CreateObject("WScript.Shell")
Set FSO = CreateObject("Scripting.FileSystemObject")

TCS.SendCommand(2030)
TrgPath = TCS.GetTextFromClip

Do While Not TempFile.AtEndOfStream
  MyFile = TempFile.ReadLine
  '----- Извлечение файла из ярлыка -----
  If FSO.GetFile(MyFile).Type = "Shortcut" Then
    MyFile = MyShell.CreateShortcut(MyFile).TargetPath
  End If
  '--------------------------------------
  If Not FSO.FileExists(TrgPath & "\" & FSO.GetFile(MyFile).Name) Then
    FSO.CopyFile MyFile, TrgPath & "\"
  End If
Loop
Сохрани в файле *.vbs, повесь файл на кнопку, в параметрах кнопки укажи %L. В скрипте для получения пути на второй панели (он будет заносится в буфер) используется TCWSHelp.
Соответственно, выделяешь файлы и ярлыки, но вместо F5 жмешь на созданную кнопку. Вместо ярлыков будут копироваться файлы. После этого нужно будет обновить (Ctrl+R) вторую файловую панель.
DjDf
Сообщения: 24
Зарегистрирован: Вт май 03, 2005 12:51

Сообщение DjDf »

Огромное спасибо!

Проделал все операции, но, к сожалению, скопировались только ярлыки, а не оригиналы. Может я что-то не так сделал?
Аватара пользователя
Batya
Сообщения: 2236
Зарегистрирован: Ср дек 15, 2004 09:51
Откуда: Москва, Россия

Сообщение Batya »

Странно.
Может у тебя тип файла по-другому называется.
Вставь после строчки MyFile = TempFile.ReadLine строчку:

Код: Выделить всё

MsgBox(FSO.GetFile(MyFile).Type)
То, что отобразит диалоговое окно для ярлыка, надо буде прописать в следующем ниже условии.
DjDf
Сообщения: 24
Зарегистрирован: Вт май 03, 2005 12:51

Сообщение DjDf »

Сенкс!!

Просто вместо If FSO.GetFile(MyFile).Type = "Shortcut" надо было написать If FSO.GetFile(MyFile).Type = "Ярлык".
Ты первый, кто наконец-то решил мою проблему. Доселе все говорили, что это нетривиально. :wink:
Аватара пользователя
Batya
Сообщения: 2236
Зарегистрирован: Ср дек 15, 2004 09:51
Откуда: Москва, Россия

Сообщение Batya »

Отлично!
Кстати, все будет проще, если вместо ярлыков использовать жесткие ссылки. Попробуй пользоваться утилитой NTFS Links.
Аватара пользователя
CaptainFlint
Сообщения: 6239
Зарегистрирован: Вт дек 14, 2004 22:34
Контактная информация:

Сообщение CaptainFlint »

DjDf
Есть ещё один вариант: установить архиваторный плагин CopyLinkTarget и выполнять просто распаковку всех этих ярлыков в нужное место. ИМХО, достаточно удобный вариант.
DjDf
Сообщения: 24
Зарегистрирован: Вт май 03, 2005 12:51

Сообщение DjDf »

Еще раз большое спасибо за советы. Мне все же больше всего понравился вариант решения Batya, но в NTFS Links насторожило то, что в результате при попытке удаления символической ссылки Проводником будет удалено всё содержимое оригинального каталога. Ну да ладно, моя проблема решена и без символических ссылок. =)
Аватара пользователя
Batya
Сообщения: 2236
Зарегистрирован: Ср дек 15, 2004 09:51
Откуда: Москва, Россия

Сообщение Batya »

DjDf
в NTFS Links насторожило то, что в результате при попытке удаления символической ссылки Проводником будет удалено всё содержимое оригинального каталога.
Меня это тоже однажды насторожило, но меня поправил, насколько я помню, именно CaptainFlint. Символическая ссылка - это ссылка на каталог. На файлы создаются жесткие ссылки. При удалении жесткой ссылки Проводником все работает корректно - другие жесткие ссылки (файлы) остаются.

Кстати, я тут подумал, что можно вышеприведенный скрипт немного упростить - тогда не понадобится TCWSHelp:

Код: Выделить всё

'==========================================================================
' Копирование файлов (в т.ч. файлов из ярлыков) из одной панели TC в другую
'
' В параметрах вызова из TC должно быть прописано:
' %L %T
'====================================================================

Dim TempFile, MyShell, FSO
Set TempFile = CreateObject("Scripting.FileSystemObject").OpenTextFile(WScript.Arguments(0), 1)
Set MyShell = WScript.CreateObject("WScript.Shell")
Set FSO = CreateObject("Scripting.FileSystemObject")

TrgPath = WScript.Arguments(1)

Do While Not TempFile.AtEndOfStream
  MyFile = TempFile.ReadLine
  '----- Извлечение файла из ярлыка -----
  If FSO.GetFile(MyFile).Type = "Shortcut" Or FSO.GetFile(MyFile).Type = "Ярлык" Then
    MyFile = MyShell.CreateShortcut(MyFile).TargetPath
  End If
  '--------------------------------------
  If Not FSO.FileExists(TrgPath & FSO.GetFile(MyFile).Name) Then
    FSO.CopyFile MyFile, TrgPath
  End If
Loop
Целевой каталог можно не вычислять, а передать от TC через %T. Обрати внимание - в параметрах кнопки надо через пробел указать %L %T.
_Johm
Сообщения: 119
Зарегистрирован: Вс май 14, 2006 20:03

Сообщение _Johm »

Как я понял, последний скрипт не работает с ярылками на папки?
Аватара пользователя
MVV
Сообщения: 4815
Зарегистрирован: Чт окт 15, 2009 10:58
Откуда: Ростов-Дон

Сообщение MVV »

Вообще, конечно, если ярлыки создаются только для временного хранения ссылок на файлы, то удобнее держать эти ссылки на временной панели. Но если ярлыки создаются по иной причине - самая банальная - доступ к ярлыкам извне ТК, то временные панели не помогут.

Попробовал я модуль CopyLinkTarget - в принципе вполне удобно. Можно выделить все ярлыки, нажать Alt+F9 - и ТК скопирует все файлы, на которые указывают ярлыки. Мне кажется, это удобнее, чем использовать скрипты. Но с ярлыками на папки он тоже не работает, но это не очень простая задача - отображать при входе в архив содержимое некоторой папки (мне приходилось такое реализовывать).
_Johm писал(а):Как я понял, последний скрипт не работает с ярылками на папки?
Судя по тому, что написано в скрипте - не работает. Если ярлыком пользуешься только из ТК, можно просто добавить ссылку на папку в Virtual Panel - тогда можно будет входить в папку по ссылке и видеть ее реальное содержимое и копировать куда нужно.

В принципе, несложно было бы написать скрипт (даже на основании указанного), который проверял бы, файлом или папкой является целевой объект ярлыка, и в зависимости от этого выполнял бы копирование файла или папки. Но это не по мне.
_Johm
Сообщения: 119
Зарегистрирован: Вс май 14, 2006 20:03

Сообщение _Johm »

JScript для копирования объектов из ярлыков (фалы/папки).
Консольный варинат для отображения сути происходящего.
Идея по извлечению "объекта" ярлыка взята из скрипта
от Batya выше.

Код: Выделить всё

/*
Title: extractlnk.js
Author: John Gurin, Russia, Ekaterinburg
Date: 2010/01/04
Desc.: Copies files/folders from *.lnk target field

TOTAL COMMANDER BUTTON==============================
====================================================
TOTALCMD#BAR#DATA
cscript.exe %COMMANDER_PATH%\SCRIPTS\files_ops\extractlnk.js
%L "%T"
C:\WINDOWS\System32\CScript.exe
extractlnk
%COMMANDER_PATH%\SCRIPTS\files_ops\

-1
====================================================
*/
//SCRIPT CONFIG
var ONLYLNK = 1; //copies only *.lnk files
var WAITONFINISH = 1; //will keep console window when finished

//DECLARING
var fso, listfile, strname, sourcename, sourcebasename, strtarget, targetname;
var t="",parentfld, dirflag, fileext, optioninput, optionflag=0, rewriteflag=false;
var filler = "   ", msg, msgflag, lnkflag, tmpmsgsrcname;
var StdIn = WScript.StdIn;

var MSG_EXIST = " already exists. Rewrite?\n" +
				"[Y]=yes [N]=no [R]=rename [Q]=quit " +
				"[A]=all [E]=never";
var MSG_SUBDIR = "ERROR: COPYING A DIRECTORY TO ITS OWN SUBDIRECTORY";
var MSG_ITSELF = "ERROR: YOU CANNOT COPY A FILE TO ITSELF";

shell = new ActiveXObject("WScript.Shell");
fso = new ActiveXObject("Scripting.FileSystemObject");

//MAIN
if(WScript.arguments.length != 2){WScript.Quit();}

listfile = fso.OpenTextFile(WScript.Arguments(0), 1);
strtarget = RemoveLastSlash(WScript.Arguments(1));

Echo("Copying to " + strtarget + "\\");
while (!listfile.AtEndOfStream){
	strname = listfile.ReadLine();
	msg = "";
	msgflag = 0;
	lnkflag = 0;
	fileext = "";
	fileext = fso.GetExtensionName(strname).toUpperCase();
	if (ONLYLNK == 1 && fileext != "LNK"){continue;}
	t = RemoveLastSlash(fso.GetParentFolderName(strname));
	dirflag = (t == parentfld) ? 1 : 0;
	if (dirflag == 0){
		parentfld = t;
		dirflag = 1;
		Echo("\n" + t + "\\");
		}

	if (fileext == "LNK" && fso.FileExists(strname)){
		lnkflag=1;
		sourcename = shell.CreateShortcut(strname).TargetPath;
		Echo(filler + Truncate(fso.GetFileName(strname)));
		}else sourcename = strname;
	
	sourcename = RemoveLastSlash(sourcename);
	sourcebasename = fso.GetFileName(sourcename);
	(tmpmsgsrcname == sourcename) ? (tmpmsgsrcname = sourcebasename) : (tmpmsgsrcname = sourcebasename + "\\");
	targetname = strtarget + "\\" + sourcebasename;
	if(sourcename==targetname){Echo(filler + " TARGET = SOURCE");continue;}

	msg = Truncate(sourcebasename);
	
	if (fso.FolderExists(sourcename)){
		(lnkflag==1) ? (msg = filler + " DIR " + msg):(msg = filler + msg);
		msg+="\\";
		if(fso.FolderExists(targetname)){
			if(optionflag==0){
				Echo(msg + MSG_EXIST);
				msgflag = 1;
				optioninput = WaitInput(1);
				switch (optioninput.toUpperCase()){
					case "Y":
						rewriteflag=true;
						break;
					case "N":
						rewriteflag=false;
						break;
					case "A":
						rewriteflag=true;
						optionflag=1;
						break;
					case "E":
						rewriteflag=false;
						optionflag=1;
						break;
					case "R":
						while(fso.FolderExists(targetname)){
							targetname=strtarget + "\\" + WaitInput(2);
						}
						rewriteflag=1;
						break;
					case "Q":
						WScript.Quit();
				}
			}
			if(rewriteflag){
				(msgflag == 0) ? Echo(msg):false;
				try{fso.CopyFolder(sourcename, targetname, true);
					}catch(e){Echo(MSG_SUBDIR);}
				}
		}else{
			Echo(msg);
			try{fso.CopyFolder(sourcename, targetname, true);
				}catch(e){Echo(MSG_SUBDIR);}
			}
		
	}else if(fso.FileExists(sourcename)){  //file operation
			(lnkflag==1) ? (msg = filler + " FILE " + msg):(msg = filler + msg);
			if(fso.FileExists(targetname)){
				if(optionflag==0){
					Echo(msg + MSG_EXIST);
					msgflag = 1;
					optioninput = WaitInput(1);
					switch (optioninput.toUpperCase()){
						case "Y":
							rewriteflag=true;
							break;
						case "N":
							rewriteflag=false;
							break;
						case "A":
							rewriteflag=true;
							optionflag=1;
							break;
						case "E":
							rewriteflag=false;
							optionflag=1;
							break;
						case "R":
							while(fso.FileExists(targetname)){
								targetname=strtarget + "\\" + WaitInput(2);
							}
							rewriteflag=1;
							break;
						case "Q":
							WScript.Quit();
					}
				}
				if(rewriteflag){
					(msgflag == 0) ? Echo(msg):false;
					try{fso.CopyFile(sourcename, targetname, true);
						}catch(e){Echo(MSG_ITSELF);}
				}
			}else{
				Echo(msg);
				try{fso.CopyFile(sourcename, targetname, true);
					}catch(e){Echo(MSG_ITSELF);}
				}
		}else{(lnkflag==1) ? Echo(filler + " TARGET MISSING " + Truncate(tmpmsgsrcname)) : 
							Echo(filler + "CANT FIND " + Truncate(tmpmsgsrcname));}
	}//while filelist
	

listfile.Close();
if(WAITONFINISH) WaitInput(0);

//FUNCTIONS
function WaitInput(mode){
	switch(mode){
		case 0:
		Echo("\nDone\nPress Enter");
		break;
		case 2:
		Echo("Enter new name:")
		break;
	}
	return(StdIn.ReadLine());
 }
function RemoveLastSlash(str){
 if (str.substring(str.length-1, str.lenght) == "\\")
	{
	str = str.slice(0,-1);
	}
	return(str);
 }
function Echo(str){
 WScript.Echo(str);
 }
function Truncate(str){
 var P = 40;
 if (str.length > P)
	{
	str = str.slice(0,P) + ".(...)." + fso.GetExtensionName(str);
	}
	return(str);
 } 
Последний раз редактировалось _Johm Чт фев 04, 2010 15:43, всего редактировалось 2 раза.
_Johm
Сообщения: 119
Зарегистрирован: Вс май 14, 2006 20:03

Сообщение _Johm »

Куда воткнуть ECHO OFF. в код или в кнопку, чтобы в консоли
не было команд?
Аватара пользователя
Batya
Сообщения: 2236
Зарегистрирован: Ср дек 15, 2004 09:51
Откуда: Москва, Россия

Сообщение Batya »

_Johm писал(а):Как я понял, последний скрипт не работает с ярылками на папки?
Так ведь никто и не заказывал.
Этот скрипт работает с ярлыками папок:

Код: Выделить всё

'===================================================
' Копирование файлов\папок (в т.ч. из ярлыков)
'
' Параметры:
' {файл-список} {целевая папка}
'
' Пример параметров при вызове из TC:
' %L "%T"
'===================================================

Dim FF, WSH, FSO, TrgPath, F, NewPath
Set FSO = CreateObject("Scripting.FileSystemObject")
Set WSH = CreateObject("WScript.Shell")
Set FF  = FSO.OpenTextFile(WScript.Arguments(0), 1)

TrgPath = WScript.Arguments(1)

Do While Not FF.AtEndOfStream
  F = FF.ReadLine
  If Right(F, 1) = "" Then F = Left(F, Len(F) - 1)
  '----- Извлечение из ярлыка -----
  If LCase(FSO.GetExtensionName(F)) = "lnk" Then
    F = WSH.CreateShortcut(F).TargetPath
  End If
  '--------------------------------
  If FSO.FileExists(F) Then
    NewPath = TrgPath & FSO.GetFile(F).Name
    If Not FSO.FileExists(NewPath) Then
      FSO.CopyFile F, TrgPath
    End If
  End If
  If FSO.FolderExists(F) Then
    NewPath = TrgPath & FSO.GetFolder(F).Name
    If Not FSO.FolderExists(NewPath) Then
      FSO.CopyFolder F, TrgPath
    End If
  End If
Loop
FF.Close
Set FF  = Nothing
Set WSH = Nothing
Set FSO = Nothing
WScript.Quit 0
Нет, я не сплю. Я просто медленно моргаю.
Ответить