4

В моем каталоге у меня есть много файлов с таким же именем и во многих других подкаталогах

пример структуры файла:

C:\ а \ первый \ hello.txt
C:\ а \ второй \ hello.txt
C:\ а \ третий \ hello.txt

Мне нужно специально найти самый последний измененный файл «hello.txt» (так как в каталоге есть и другие файлы) и скопировать содержащую его папку в C:\b.

Я очень новичок в партии, поэтому объяснения будут фантастическими :)

2 ответа2

2

Это неуклюжая коллекция команд, и, без сомнения, кто-то умнее меня (например, gratia) превратит это во что-то гораздо меньшее и более лаконичное, но иногда лучше научиться видеть, как вращаются все шестерни.

Этот пакетный файл, или «скрипт», использует cut, head и sed из Core Utilities для Windows (с открытым исходным кодом) http://gnuwin32.sourceforge.net/packages/coreutils.htm, который, если вы хотите сделать что-либо пакетной записи файлов, делает вашу жизнь оооочень проще.

C:      
cd \a  
del temp.tmp  
for /f "eol=: delims=" %%F in ('dir hello.txt /b /s') do @echo %%~tF %%F >> temp.tmp  
sort /r temp.tmp > result.tmp   
head -1 result.tmp > temp.tmp  
cut -d: -f 3 temp.tmp | sed s/hello.txt// > temp.tmp  
set /p SOU=<temp.tmp  
CD %SOU%  
copy *.* C:\b\ 
dir c:\b 

Чего-чего? Вот небольшой комментарий, начиная с четвертой строки, который я адаптировал (программисты редко говорят, что украл) из работы гения над StackOverflow:

for /f "eol=: delims=" %%F in ('dir hello.txt /b /s') do @echo %%~tF %%F >> temp.tmp

который создает рабочий файл с именем temp.tmp, строится построчно, перечисляя каждый файл hello.txt в текущем каталоге; каждая строка начинается с даты и времени hello.txt, за которым следует абсолютный путь к hello.txt, который выглядит как

05.10.2008 09:27 C:\a\1\hello.txt
05.10.2008 09:29 C:\a\2\hello.txt
05.10.2008 09:32 C:\a\3\hello.txt

sort /r temp.tmp > result.tmp  

берет содержимое файла temp.tmp и сортирует его в обратном порядке, записывая в файл result.tmp, перезаписывая все, что было раньше (если что-то было), или создавая файл, если не было файла result.tmp, получая:

05.10.2008 09:32 C:\a\3\hello.txt
05.10.2008 09:29 C:\a\2\hello.txt
05.10.2008 09:27 C:\a\1\hello.txt

head -1 result.tmp > temp.tmp  

Windows делает что-то, чего не знает Windows, поэтому нам пришлось получить пакет GNU Core Utilities с открытым исходным кодом, как в пиве, чтобы получить команду head, которая в данном случае просто берет первую строку result.tmp и записывает ее в temp.tmp, перезаписывая все, что было в temp.tmp раньше (единственный оператор > '' redirection ' перезаписывает; оператор >> объединяет, добавляя к тому, что уже было в файле), что дает нам:

05.10.2008 09:32 C:\a\3\hello.txt

cut -d: -f 3 temp.tmp | sed s/hello.txt// > temp.tmp  

Эта строка использует команду cut, чтобы отобразить только третье поле (без даты и времени) файла temp.tmp и « передать » его другой маленькой программе sed, которая настолько невероятна, что простые слова не могут объяснить все, что она может сделать. Здесь мы используем его, чтобы найти hello.txt и удалить его из того, что мы нашли в temp.tmp, и отправить его для перезаписи temp.tmp ; теперь он просто содержит путь к самому новому экземпляру hello.txt :

\ А \ 3 \

(Если хотите, вы можете объединить строки 5, 6 и 7 в одну строку с

sort /r temp.tmp | head -1 | cut -d: -f 3 | sed s/hello.txt// > temp.tmp 

но я держал их отдельно для учебных целей.)

Хорошо, теперь у нас есть абсолютный путь к каталогу файлов, из которого мы хотим скопировать, который находится в temp.tmp, но нам нужно использовать его в командном файле, так что с командой

set /p SOU=<temp.tmp 

мы устанавливаем переменную, SOU, к тому, что находится в temp.tmp.

CD %SOU%  

изменяет рабочий каталог на тот, где находился самый новый экземпляр hello.txt , и

copy *.* C:\b\  

копирует свои файлы в \b на диске C:

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

Примечание: когда вы тестируете, построчно, вы используете один% для переменных; как только это сработает и вы поместите его в пакетный файл, вы используете двойной %%, что меня сильно смущало, пока я не прочитал объяснение, в котором упоминалось об этом.

0

Если у вас есть доступ к bash (возможно, через cygwin, WSL, min-gw и т.д.), Вот одна строка (если вы уже находитесь в нужном родительском каталоге:

cp $(dirname `find . -type f -exec ls -l {} --time-style=+%s \; | sort -nrk 7 | awk '{print $8}' | head -1`)/* "c:\b"

это предположить cygwin. Для других вам может понадобиться немного изменить целевой путь. Возможно, вам сначала нужно убедиться, что dirname , find , sort , awk , head доступны

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .