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

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

@echo off

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

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

Ответы [ 3 ]

0 голосов
/ 11 апреля 2019

Вот решение в одну строку

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 или -ReadCount опция Get-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 /?

0 голосов
/ 11 апреля 2019

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

$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 s в первой строке, прежде чем тестировать его.

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

0 голосов
/ 11 апреля 2019

Создайте собственную команду 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

Cut.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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...