Pull to refresh

Comments 26

UFO just landed and posted this here
Этот вариант тоже повиснет если выходной файл уже существует.
Убогость cmd.exe конечно поражает, приходится аж что-то вот такое писать:
for %f in (*.txt) do type "%f" >> output.txt
Причем оно даже результат к самому себе не дописывает в цикле, а вдруг нам именно это и нужно было
всю жизнь пытался понять как люди понимают что там написано. вот что значит этот гребаный знак % вот просто к чему он там?
Просто обязательный префикс для параметров и переменных цикла. Почти то же самое, что и знак $ в баше, powershell или php.

Не спец по PS, но полагаю, что идея в ленивом исполнении. Т.е. сначала команда извлекает первый файл, затем — его содержимое, возможно — одну строку, затем дописывает строки в конец выходного файла, пока первый файл не закончится. Потом в какой-то момент доходит до вашего выходного файла и лениво начинает тянуть из него строки, попутно их записывая. Очевидно, строки не заканчиваются. 25% загрузки CPU говорят о том, что у вас скорее всего двухъядерный лэптоп с hyperthreading enabled.
Я попробовал поиграть с командами, решение (вроде как) оказалось простым:


> echo "Hello, World 1!" > test1.txt
> echo "Hello, World 2!" > test2.txt
> (ls | cat) > out.txt
> ls
Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2018-12-19     20:36             70 out.txt
-a----       2018-12-19     20:36             36 test1.txt
-a----       2018-12-19     20:36             36 test2.txt
> cat out.txt
Hello, World 1!
Hello, World 2!

Попробуйте — вдруг будет работать.


UPD Здесь до меня по сути то же самое написали.

Ваше (ls | cat) > out.txt — это ровно то же самое, что и авторское get-childitem | get-content | out-file result.txt, только выходной файл называется по-другому.


Вам просто повезло, что имя вашего файла оказалось лексикографически меньше всех остальных файлов в директории, а потому powershell его прочитал самым первым, когда он еще был пустым.

UPD: почему-то я первый раз не обратил внимания на скобки, даже когда скопировал их. Да, со скобками работать будет, скобки разрывают конвейер и материализуют последовательность.

Но надо понимать, что эта команда загрузит содержимое всех файлов в память.
убогостью средства cmd.exe

Хм…
for %R in (*.txt) do  type %R >> result.txt
А если эту строку вписать в файл merge.cmd и запустить, сработает? У меня почему-то только в консоли cmd такая строка работает, а если батником запускать, находящимся в папке с требуемыми файлами, никакого эффекта.

в батнике надо % удваивать:


for %%R in (*.txt) do @type %%R>> rezult.tx

ну и плюс дурная идея в том же каталоге создавать txt файл, который тоже считается и допишется. Это к удвоению данных :)

В батнике надо писать %% перед переменной.
Серьезная подстава от языка.

Проверил, 3 текстовых файла в папке было, объединились, но результат получился на 1 байт больше суммы исходных, в конце файла символ с кодом 0x1A зачем-то дописался…
0x1A — это EOF. Legacy, ещё из DOS тянется, что поделать.
Можно склеивать так — все символы 0x1a будут вырезаны, новые добавлены не будут:
copy *.txt result.txt /b
х его з, но изначальная строчка будет работать нормально как задумано:
Get-ChildItem -Filter *.log | Get-Content | Out-File result.txt

Вот если бы result.txt был result.log, тогда да, еще возможна такая ситуация. Не знаю почему вам не был очевиден такой момент. Он же будет по конвееру передавать все по одному элементу, попадающему в шаблон, поэтому да, вечный loop. Можно еще так:
dir | cat > result.txt
Get-ChildItem -filter *.log | Where-Object Name -notlike 'result.log'| Get-Content |Out-File result.log

А зачем писать итоговый файл в одну папку с исходными и создавать проблему на пустом месте?

Статья больше о том, что это поведение ненормальное и непредсказуемое. Путей решения есть много, если знаешь, что проблема есть.
Вспомнился анекдот:
Приходит мужик к врачу и говорит:
— Доктор, я когда рукой двигаю, у меня вот тут болит
— А когда не двигаете — не болит?
— Нет.
— Ну так просто не двигайте рукой!

Насчёт — ненормальное и непредсказуемое — Вы погорячились. Просто, видимо, опыта мало.
Бомбануть может где угодно. Например, у Вас в каталоге есть файлы "rm", "-Rf", а вы матчите список файлов шеллом (через "*"). Или просто список имён файлов вылезает за пределы определенного лимита...


По статье — для начала неплохо. Кейс действительно интересный. Но очень рекомендую исправить все опечатки/описки, т.к. выглядит неаккуратненько.

Убогость это вот это:
Get-ChildItem -filter *.log | Where-Object Name -notlike 'result.log'| Get-Content |Out-File result.log

Против вот этого:
copy *.txt result.txt /b

(код взять из соседних комментов).
UFO just landed and posted this here
В Линуксе вообще с командной строкой всё хорошо.
UFO just landed and posted this here
Обознатушки — перепрятушки.
В курсе — никсы благотворно влияют на продукцию МС, а то бы до сих пор нужно было бы выписывать «Войну и Мир» в командой строке. Жаль алиасы не везде есть, но их можно же определять вручную.
Странно что никто не вспомнил про -Exclude:
ls *.log -Exclude 'result.log' | cat > 'result.log'

полная версия:
Get-ChildItem -Filter *.log -Exclude 'result.log'| Get-Content | Out-File result.log
Sign up to leave a comment.

Articles