Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Скриптовые языки администрирования Windows » Любой язык - [решено] Удалить последний байт в файле

Ответить
Настройки темы
Любой язык - [решено] Удалить последний байт в файле

Пользователь


Сообщения: 93
Благодарности: 2

Профиль | Отправить PM | Цитировать


Изменения
Автор: pzh2393
Дата: 05-12-2014
Прошу помощи в написании скрипта который позволил бы удалить (отрезать) последний байт в файле.

Немного объясню.. есть у меня группа JPEG файлов (порядка полтысячи) у которых по непонятной мне причине в конец дописан символ перевода строки А0.
В принципе с этим жить можно, но вот при поиске дубликатов из-за этой разницы получаю не тот результат на который рассчитывал.
Использовать утилиты проверяющие по содержимому (т.е. более долго) пока не хочется, проще у найденных вырезать "лишний" байт в конце.
Очень прошу помочь со скриптом.

Отправлено: 19:34, 01-12-2014

 

Ветеран


Сообщения: 27449
Благодарности: 8087

Профиль | Отправить PM | Цитировать


На WSH:
Скрытый текст
Код: Выделить весь код
Option Explicit

Const adTypeBinary = 1
Const adSaveCreateOverWrite = 2


Dim strSourceFolder

Dim objFile


If WScript.Arguments.Count = 1 Then
	strSourceFolder = WScript.Arguments.Item(0)
	
	With WScript.CreateObject("Scripting.FileSystemObject")
		If .FolderExists(strSourceFolder) Then
			For Each objFile In .GetFolder(strSourceFolder).Files
				Select Case LCase(.GetExtensionName(objFile.Name))
					Case "jpg", "jpeg", "jpe"
						With WScript.CreateObject("ADODB.Stream")
							.Type = adTypeBinary
							.Open
							
							.LoadFromFile objFile.Path
							
							.Position = objFile.Size - 1
							
							If AscB(MidB(.Read(1), 1, 1)) = &H0A Then
								.Position = objFile.Size - 1
								.SetEOS
								
								.SaveToFile objFile.Path, adSaveCreateOverWrite
							End If
							
							.Close
						End With
					Case Else
						' Nothing to do
				End Select
			Next
		Else
			WScript.Echo "Can't find source folder [" & strSourceFolder & "]."
			WScript.Quit 2
		End If
	End With
Else
	WScript.Echo "Usage: " & WScript.ScriptName & " <Source folder>"
	WScript.Quit 1
End If

WScript.Quit 0

Достаточно просто перетащить целевую папку на скрипт. Будут найдены все файлы в этой папке с расширениями "jpg", "jpeg", "jpe", и, если содержимым их последнего байта окажется «0x0A» — они будут урезаны по размеру на этот последний байт. Вложенные папки не обрабатываются. Резервных копий исходных файлов не делается.
Это сообщение посчитали полезным следующие участники:

Отправлено: 06:02, 02-12-2014 | #2



Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля.


Ветеран


Сообщения: 27449
Благодарности: 8087

Профиль | Отправить PM | Цитировать


Примерный аналог на PowerShell (в качестве самообучения):
Скрытый текст
Код: Выделить весь код
Param(
    [string]$sSourceFolder = "E:\Песочница\0411"
)

if(Test-Path -Path $sSourceFolder -PathType Container) {
    Get-ChildItem -Path $sSourceFolder -Recurse -Include "*.jpg", "*.jpeg", "*.jpe" |`
        Where-Object -FilterScript {
            -not $_.PSIsContainer
        } | ForEach-Object -Process {
            $oFileStream = $_.Open([System.IO.FileMode]::Open)
            [void]$oFileStream.Seek(-1, [System.IO.SeekOrigin]::End)
            
            if($oFileStream.ReadByte() -eq 0x0A) {
                Write-Host "* $($_.Name)" -ForegroundColor Green
                $oFileStream.SetLength($oFileStream.Position - 1)
            } else {
                Write-Host "  $($_.Name)"
            }
            
            $oFileStream.Close()
            $oFileStream.Dispose()
        }
} else {
    Write-Host "Can't find source folder [$sSourceFolder]." -ForegroundColor Red
}

P.S. Внезапно обнаружил, что Drag-n-Drop на «.ps1» не включён по умолчанию .
Это сообщение посчитали полезным следующие участники:

Отправлено: 06:49, 02-12-2014 | #3


Пользователь


Сообщения: 93
Благодарности: 2

Профиль | Отправить PM | Цитировать


Цитата Iska:
На WSH: »
Спасибо!
Только при перетаскивании на скрипт выбивает окно с ошибкой "There is no script file specified".


На PowerShell работает нормально, но как-то не удобно каждый раз вручную менять путь в "[string]$sSourceFolder = "E:\..."


P.S. Было бы очень желательно если бы скрипт запускался не перетаскиванием папки, а обычным "двойным щелчком".

Отправлено: 12:46, 02-12-2014 | #4


Ветеран


Сообщения: 27449
Благодарности: 8087

Профиль | Отправить PM | Цитировать


Цитата pzh2393:
Только при перетаскивании на скрипт выбивает окно с ошибкой "There is no script file specified". »
Сохраните не с расширеним «.wsh», а с расширением «.vbs».

Цитата pzh2393:
На PowerShell работает нормально, но как-то не удобно каждый раз вручную менять путь в "[string]$sSourceFolder = "E:\..."
»
Верю. Но у меня перетаскивание с типом «.ps1» не работает. А у Вас?

Цитата pzh2393:
P.S. Было бы очень желательно если бы скрипт запускался не перетаскиванием папки, а обычным "двойным щелчком". »
А дальше? Откуда брать имя целевой папки? Запрашивать каждый раз? Поверьте, это куда неудобнее.
Это сообщение посчитали полезным следующие участники:

Отправлено: 13:04, 02-12-2014 | #5


Пользователь


Сообщения: 93
Благодарности: 2

Профиль | Отправить PM | Цитировать


Спасибо Iska.

А можно ещё попросить вариант скрипта на WSH срабатывающего только для одного файла а не для всей папки?
имя файла будет передаваться командой "cut.vbs %1"

Отправлено: 14:12, 02-12-2014 | #6


Ветеран


Сообщения: 27449
Благодарности: 8087

Профиль | Отправить PM | Цитировать


Как-то так:
Скрытый текст
Код: Выделить весь код
Option Explicit

Const adTypeBinary = 1
Const adSaveCreateOverWrite = 2


Dim strSourceFile

Dim objFile


If WScript.Arguments.Count = 1 Then
	strSourceFile = WScript.Arguments.Item(0)
	
	With WScript.CreateObject("Scripting.FileSystemObject")
		If .FileExists(strSourceFile) Then
			Set objFile = .GetFile(strSourceFile)
			
			Select Case LCase(.GetExtensionName(objFile.Name))
				Case "jpg", "jpeg", "jpe"
					With WScript.CreateObject("ADODB.Stream")
						.Type = adTypeBinary
						.Open
						
						.LoadFromFile objFile.Path
						
						.Position = objFile.Size - 1
						
						If AscB(MidB(.Read(1), 1, 1)) = &H0A Then
							.Position = objFile.Size - 1
							.SetEOS
							
							.SaveToFile objFile.Path, adSaveCreateOverWrite
						Else
							WScript.Echo "Last byte of source file [" & strSourceFile & "] is not a 0x0A value."
						End If
						
						.Close
					End With
				Case Else
					WScript.Echo "Source file [" & strSourceFile & "] probably not a jpeg file."
					WScript.Quit 3
			End Select
		Else
			WScript.Echo "Can't find source file [" & strSourceFile & "]."
			WScript.Quit 2
		End If
	End With
Else
	WScript.Echo "Usage: " & WScript.ScriptName & " <Source file>"
	WScript.Quit 1
End If

WScript.Quit 0

Аналогично можно перетаскивать файл на скрипт.
Это сообщение посчитали полезным следующие участники:

Отправлено: 14:27, 02-12-2014 | #7


Ветеран


Сообщения: 27449
Благодарности: 8087

Профиль | Отправить PM | Цитировать


Из письма в PM:
Скрытый текст
Цитата pzh2393:
Добрый день!

Прошу прощения, что обращаюсь напрямую, но восстанавливать эту тему (http://forum.oszone.net/thread-291932.html) считаю не имеет смысла.

Оказалось, что часть из моих файлов в конце содержат не только символ перевода строки, но и ряд других, включая просто "обнуленные" (00 00 00 00...) последовательности непостоянного размера.

Можно ли подредактировать скрипт таким образом, чтобы удалялся не только последний байт, а все лишние от конца вплоть до FF D9 (по спецификации конец JPEG файла) ?

Прошу помочь, поскольку в скриптописании (особенно на WHS) не силен.

Именно что имеет смысл. Надо было писать именно здесь, и затем, если очень хочется, дать ссылку на новое сообщение в PM.

Поскольку непосредственная работа с ByteArray в WSH не предусмотрена — наш выбор PowerShell:
Скрытый текст
Код: Выделить весь код
Param(
    [string]$sSourceFolder = "E:\Песочница\0411"
)

if(Test-Path -Path $sSourceFolder -PathType Container) {
    Get-ChildItem -Path $sSourceFolder -Recurse -Include "*.jpg", "*.jpeg", "*.jpe" |`
        Where-Object -FilterScript {
            -not $_.PSIsContainer
        } | ForEach-Object -Process {
            $oFileStream = $_.Open([System.IO.FileMode]::Open)
            
            [void]$oFileStream.Seek(-2, [System.IO.SeekOrigin]::End)
            
            if($oFileStream.ReadByte() -eq 0xFF -and $oFileStream.ReadByte() -eq 0xD9) {
                Write-Host "  $($_.Name)"
            } else {
                $bFound = $false
                
                for($i = $oFileStream.Length - 3; $i -ge 0; $i--) {
                    [void]$oFileStream.Seek($i, [System.IO.SeekOrigin]::Begin)
                    
                    if($oFileStream.ReadByte() -eq 0xFF -and $oFileStream.ReadByte() -eq 0xD9) {
                        $oFileStream.SetLength($oFileStream.Position)
                        
                        $bFound = $true
                        break
                    }
                }
                
                if($bFound) {
                    Write-Host "* $($_.Name)" -ForegroundColor Green
                } else {
                    Write-Host "  $($_.Name)" -ForegroundColor Red
                }
            }
            
            $oFileStream.Close()
            $oFileStream.Dispose()
        }
} else {
    Write-Host "Can't find source folder [$sSourceFolder]." -ForegroundColor Red
}
Это сообщение посчитали полезным следующие участники:

Отправлено: 15:14, 06-12-2014 | #8


Пользователь


Сообщения: 93
Благодарности: 2

Профиль | Отправить PM | Цитировать


А что-то вроде этого на WSH не сработает?
Скрытый текст
Код: Выделить весь код
Option Explicit

Const adTypeBinary = 1
Const adSaveCreateOverWrite = 2


Dim strSourceFolder

Dim objFile


If WScript.Arguments.Count = 1 Then
	strSourceFolder = WScript.Arguments.Item(0)
	
	With WScript.CreateObject("Scripting.FileSystemObject")
		If .FolderExists(strSourceFolder) Then
			For Each objFile In .GetFolder(strSourceFolder).Files
				Select Case LCase(.GetExtensionName(objFile.Name))
					Case "jpg", "jpeg", "jpe"
						With WScript.CreateObject("ADODB.Stream")
							.Type = adTypeBinary
							.Open
							
							.LoadFromFile objFile.Path
							
							.Position = objFile.Size - 1
							
							If AscB(MidB(.Read(1), 1, 1)) = &HD9 Then
							' Nothing to do
							Else
								.Position = objFile.Size - 1
								.SetEOS
								
								.SaveToFile objFile.Path, adSaveCreateOverWrite
							End If
							
							.Close
						End With
					Case Else
						' Nothing to do
				End Select
			Next
		Else
			WScript.Echo "Can't find source folder [" & strSourceFolder & "]."
			WScript.Quit 2
		End If
	End With
Else
	WScript.Echo "Usage: " & WScript.ScriptName & " <Source folder>"
	WScript.Quit 1
End If

WScript.Quit 0

скриптописец конечно из меня "нулевой", но может все же имеет смысл?

Отправлено: 15:51, 06-12-2014 | #9


Ветеран


Сообщения: 27449
Благодарности: 8087

Профиль | Отправить PM | Цитировать


Цитата pzh2393:
А что-то вроде этого на WSH не сработает? »
Вы и мёртвого уговорите. Пробуйте:
Скрытый текст
Код: Выделить весь код
Option Explicit

Const adTypeBinary = 1
Const adSaveCreateOverWrite = 2


Dim strSourceFolder

Dim objFile

Dim i


If WScript.Arguments.Count = 1 Then
	strSourceFolder = WScript.Arguments.Item(0)
	
	With WScript.CreateObject("Scripting.FileSystemObject")
		If .FolderExists(strSourceFolder) Then
			For Each objFile In .GetFolder(strSourceFolder).Files
				Select Case LCase(.GetExtensionName(objFile.Name))
					Case "jpg", "jpeg", "jpe"
						With WScript.CreateObject("ADODB.Stream")
							.Type = adTypeBinary
							.Open
							
							.LoadFromFile objFile.Path
							
							.Position = objFile.Size - 2
							
							If AscB(MidB(.Read(1), 1, 1)) = &HFF And AscB(MidB(.Read(1), 1, 1)) = &HD9 Then
								' Nothing to do
							Else
								For i = .Size - 3 To 0 Step -1
									.Position = i
									
									If AscB(MidB(.Read(1), 1, 1)) = &HFF And AscB(MidB(.Read(1), 1, 1)) = &HD9 Then
										.SetEOS
										.SaveToFile objFile.Path, adSaveCreateOverWrite
										
										Exit For
									End If
								Next
							End If
							
							.Close
						End With
					Case Else
						' Nothing to do
				End Select
			Next
		Else
			WScript.Echo "Can't find source folder [" & strSourceFolder & "]."
			WScript.Quit 2
		End If
	End With
Else
	WScript.Echo "Usage: " & WScript.ScriptName & " <Source folder>"
	WScript.Quit 1
End If

WScript.Quit 0
Это сообщение посчитали полезным следующие участники:

Отправлено: 19:07, 06-12-2014 | #10



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Скриптовые языки администрирования Windows » Любой язык - [решено] Удалить последний байт в файле

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
CMD/BAT - [решено] Как удалить последнюю строку в текстовом файле? ivanxam Скриптовые языки администрирования Windows 35 18-09-2018 08:33
CMD/BAT - [решено] Помогите удалить повторяющиеся строки в файле. kolkin-alexandr Скриптовые языки администрирования Windows 9 03-11-2017 23:21
CMD/BAT - [решено] Удалить пустую строку в файле .txt denntl Скриптовые языки администрирования Windows 2 18-07-2013 11:48
CMD/BAT - [решено] Удалить в текстовом файле по условию AlexVong Скриптовые языки администрирования Windows 1 21-11-2010 11:53
[решено] Изменить байт в файле по смещению. semiono AutoIt 2 29-08-2010 22:57




 
Переход