Ищете решения MORE/MOVE, которые могут обрабатывать файлы с более чем 65534 строками

У меня есть множество файлов .CSV с уникальными именами, из которых мне нужно удалить первые 17 строк. Некоторые из этих файлов превышают 65534 строки, поэтому мой пакетный сценарий MORE/MOVE не работает. Ищем альтернативные решения.

@echo off

for %%a in (*.csv) do (
    more +17 "%%a" >"%%a.new"
    move /y "%%a.new" "%%a" >nul
)

Независимо от количества введенных строк, я хочу удалить 17 строк заголовков и создать новый файл со всеми оставшимися строками.

В зависимости от масштаба вашего numerous использование простого for для итерации файлов может быть опасным, поскольку файлы могут обрабатываться несколько раз. Если это вариант, я бы использовал для этого PowerShell.

user6811411 10.04.2019 21:55

Команда FOR /F имеет возможность пропуска.

Squashman 11.04.2019 04:19
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
140
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Создайте свою собственную команду cut. Это VBScript, перенесенный на VB.NET.

Резать

cut {t|b} {i|x} NumOfLines

Сокращает количество строк сверху или снизу файла.

t - top of the file
b - bottom of the file
i - include n lines
x - exclude n lines

Пример

cut t i 5 < "%systemroot%\win.ini"

Cut.bat

REM Cut.bat
REM This file compiles Cut.vb to Cut.exe
REM Cut.exe Removes specified from top or bottom of lines from StdIn and writes to StdOut 
REM To use 
REM cut {t|b} {i|x} NumOfLines
Rem Cuts the number of lines from the top or bottom of file.
Rem t - top of the file
Rem b - bottom of the file
Rem i - include n lines
Rem x - exclude n lines
Rem
Rem Example - Includes first 5 lines Win.ini
Rem 
Rem cut t i 5 < "%systemroot%\win.ini"
"C:\Windows\Microsoft.NET\Framework\v4.0.30319\vbc.exe" /target:exe /out:"%~dp0\Cut.exe" "%~dp0\Cut.vb" /verbose
pause

Вырезать.vb

'DeDup.vb
Imports System
Imports System.IO
Imports System.Runtime.InteropServices
Imports Microsoft.Win32

Public Module DeDup
Sub Main
    Dim Arg() As Object
    Dim RS as Object
    Dim LineCount as Object
    Dim Line as Object
    Arg = Split(Command(), " ")
    rs = CreateObject("ADODB.Recordset")
    With rs
        .Fields.Append("LineNumber", 4)
        .Fields.Append("Txt", 201, 5000) 
        .Open
        LineCount = 0
        Line=Console.readline
        Do Until Line = Nothing
            LineCount = LineCount + 1
            .AddNew
            .Fields("LineNumber").value = LineCount
            .Fields("Txt").value = Console.readline
            .UpDate
            Line = Console.ReadLine
        Loop

        .Sort = "LineNumber ASC"

        If LCase(Arg(0)) = "t" then
            If LCase(Arg(1)) = "i" then
                .filter = "LineNumber < " & LCase(Arg(2)) + 1
            ElseIf LCase(Arg(1)) = "x" then
                .filter = "LineNumber > " & LCase(Arg(2))
            End If
        ElseIf LCase(Arg(0)) = "b" then
            If LCase(Arg(1)) = "i" then
                .filter = "LineNumber > " & LineCount - LCase(Arg(2))
            ElseIf LCase(Arg(1)) = "x" then
                .filter = "LineNumber < " & LineCount - LCase(Arg(2)) + 1
            End If
        End If

        Do While not .EOF
            Console.writeline(.Fields("Txt").Value)
            .MoveNext
        Loop
    End With

End Sub 
End Module

Вот однострочное решение

for %%a in (*.txt) do powershell -Com "sc -Path '%%a' -Value (gc '%%a' | select -Skip 17)"

где gc и sc — псевдонимы по умолчанию для Get-Content и Set-Content соответственно. Смотрите также

Если ваши файлы огромны, лучше читать по строкам или блокам, что также можно легко реализовать с помощью файловых функций, [IO.File]::OpenText или опции -ReadCountGet-Content в PowerShell.


Как упомянул Сквошман, for /f также имеет возможность пропускать строки в начале файла.

for %%a in (*.csv) do (
    for /f "usebackq skip=17 delims = " %%l in ("%%f") do @echo(%%l>>"%%a.new"
    move /y "%%a.new" "%%a" >nul
)

Но это не сработает, если ваш файл содержит строки со специальными символами, такими как & или |. Для получения дополнительной информации об этом бегите for /?

Ваши пакетные решения работают с & или |, но единственная проблема связана с пустыми строками или строками, начинающимися с ;

jeb 17.03.2021 07:41
Ответ принят как подходящий

Вот вариант ; этот использует поток для обслуживания ваших больших файлов:

$csvs = Get-ChildItem -Path "P:\ath to\your csvs" -Filter *.csv
foreach ( $csv in $csvs ) {
    $fin = New-Object System.IO.StreamReader( $csv.FullName )
    $fout = New-Object System.IO.StreamWriter( $csv.FullName+".new" )
    try {
        for( $s = 1; $s -le 17 -and !$fin.EndOfStream; $s++ ) {
            $fin.ReadLine()
        }
        while( !$fin.EndOfStream ) {
            $fout.WriteLine( $fin.ReadLine() )
        }
    }
    finally {
        $fout.Close()
        $fin.Close()
    }
}

Просто измените путь к своим .csv в первой строке, прежде чем тестировать его.

Я намеренно не удаляю исходные файлы, просто добавляя .new к новым именам файлов, чтобы у вас было время проверить результаты, проверить скорость и т. д. Я оставлю вам возможность включить переименование/удаление или перемещение, если вы чувствуете необходимость расширения функционала.

Другие вопросы по теме