Mam dwa pliki tekstowe i chcę znaleźć różnice między nimi za pomocą programu Windows Powershell. Czy jest dostępne coś podobnego do narzędzia Unix diff? Czy jest inny sposób, którego nie rozważałem?
Próbowałem porównać obiekt, ale otrzymałem ten tajemniczy wynik:
PS C:\> compare-object one.txt two.txt
InputObject SideIndicator
----------- -------------
two.txt =>
one.txt <=
windows
powershell
Brian Willis
źródło
źródło
-SyncWindow 0
to naprawić, ale nie jestem pewien, czy zostało to niedawno wprowadzone. Nie jest to jednak szczególnie mądre.Prostszym sposobem na to jest napisanie:
źródło
diff
, jak zauważają inne odpowiedzi tutaj. A kiedy użyłem bardziej złożonego wyrażenia zamiastcat
otrzymałem niepoprawne dane wyjściowe, więc dołączę się do pozostałych w zaleceniu, aby uniknąć robienia tego w PowerShell, jeśli pochodzisz z * nix.Lub możesz użyć
fc
polecenia DOS w ten sposób (pokazuje to wynik obu plików, więc będziesz musiał skanować w poszukiwaniu różnic):fc
jest aliasem polecenia cmdlet Format-Custom, dlatego należy wprowadzić polecenie asfc.exe
. Należy pamiętać, że wiele narzędzi DOS nie obsługuje kodowania UTF-8.Możesz także odrodzić proces CMD i uruchomić
fc
go.To instruuje PowerShell, aby rozpocząć proces z programem „cmd” przy użyciu parametrów w cudzysłowach. W cudzysłowach znajduje się opcja cmd „/ c”, która uruchamia polecenie i kończy działanie. Właściwe polecenie uruchamiane przez cmd w tym procesie
fc filea.txt fileb.txt
przekierowuje dane wyjściowe do plikudiff.txt
.Możesz używać DOS
fc.exe
z poziomu PowerShell.źródło
diff na * nix nie jest częścią powłoki, ale osobną aplikacją.
Czy jest jakiś powód, dla którego nie można po prostu użyć pliku diff.exe w programie PowerShell?
Możesz pobrać wersję z pakietu UnxUtils ( http://unxutils.sourceforge.net/ )
źródło
git diff
, ponieważ już go zainstalowałem. Anifc.exe
nieCompare-Object
wyprodukowałem oczekiwanych wyników.porównaj-obiekt (alias diff) jest żałosny, jeśli spodziewasz się, że będzie on zachowywał się jak diff uniksowy. Wypróbowałem diff (plik gc1) (plik gc2), a jeśli linia jest za długa, nie widzę rzeczywistego pliku różnicowego i, co ważniejsze, nie mogę powiedzieć, na którym numerze linii znajduje się plik różnicowy.
Kiedy próbuję dodać -passthru, teraz widzę różnicę, ale tracę plik, w którym jest różnica, i nadal nie otrzymuję numeru linii.
Moja rada, nie używaj programu PowerShell do znajdowania różnic w plikach. Jak ktoś zauważył, fc działa i działa trochę lepiej niż porównywać obiekty, a jeszcze lepiej jest pobieranie i używanie prawdziwych narzędzi, takich jak emulator unixowy, o którym wspomniał Mikeage.
źródło
-SyncWindow
Ignoruje kolejność), ponieważ domyślnie jest to maksymalne. Ustawienie tej wartości na 0 nie powoduje, że działa tak samo jakdiff
... A kiedy przekazałem potok(... | select-object ...)
jako dane wejściowe, po prostu wydrukowałem bzdury, więc się poddałem.Jak zauważyli inni, jeśli spodziewałeś się wyjścia diff unix-y, użycie aliasu diff PowerShell mocno cię zawiodło. Po pierwsze, musisz trzymać rękę przy czytaniu plików (z gc / get-content). Po drugie, wskaźnik różnicy znajduje się po prawej stronie, z dala od treści - to koszmar czytelności.
Rozwiązaniem dla każdego, kto szuka zdrowego rozsądku, jest
dodaj linię
Argument -force jest wymagany, ponieważ Powershell jest dość cenny w przypadku tego konkretnego wbudowanego aliasu. Jeśli ktoś jest zainteresowany, po zainstalowaniu GnuWin32, dołączam również następujące informacje do mojego profilu PowerShell:
Głównie dlatego, że Powershell nie rozumie argumentów uruchamianych razem i pisania, na przykład „rm -Force -Recurse” jest znacznie większym wysiłkiem niż „rm -rf”.
Program PowerShell ma kilka fajnych funkcji, ale jest kilka rzeczy, których nie powinien po prostu dla mnie robić.
źródło
WinMerge to kolejne dobre narzędzie do porównywania oparte na GUI.
źródło
Istnieje również Windiff, który zapewnia interfejs GUI (świetny do użytku z programami CVS / SVN opartymi na GUI)
źródło
fc.exe
jest lepszy do porównywania tekstu, ponieważ zaprojektowano go do działania jak * nix diff, tzn. porównuje linie sekwencyjnie, pokazując rzeczywiste różnice i próbując ponownie zsynchronizować (jeśli różne sekcje mają różne długości). Ma także kilka przydatnych opcji sterowania (tekst / binarny, rozróżnianie wielkości liter, numery linii, długość resynchronizacji, rozmiar bufora niedopasowania) i zapewnia status wyjścia (-1 zła składnia, 0 takich samych plików, 1 pliki różnią się, brak 2 plików). Jako (bardzo) stare narzędzie DOS ma kilka ograniczeń. Co najważniejsze, nie działa on automatycznie z Unicode, traktując 0 MSB znaków ASCII jako terminator linii, więc plik staje się sekwencją 1 linii znaków (@kennycoc: użyj opcji / U, aby określić, że OBIE pliki są Unicode, a WinXP i nowsze ), a także ma sztywny bufor o rozmiarze 128 znaków (128 bajtów ASCII,Obiekt porównywania służy do ustalenia, czy 2 obiekty są identyczne pod względem członków. jeśli obiekty są kolekcjami, to są one traktowane jako ZESTAWY (patrz pomoc porównania-obiekt), tj. kolekcje NIEZGODNE bez duplikatów. 2 zestawy są równe, jeśli mają takie same elementy członkowskie, niezależnie od kolejności lub duplikatów. To poważnie ogranicza jego przydatność do porównywania plików tekstowych pod kątem różnic. Po pierwsze, domyślne zachowanie zbiera różnice, dopóki cały obiekt (plik = tablica ciągów) nie zostanie sprawdzony, tracąc w ten sposób informacje dotyczące położenia różnic i zaciemniając, które różnice są sparowane (i nie ma pojęcia numeru linii dla SET ciągów). Użycie opcji -synchwindow 0 spowoduje, że różnice zostaną wyemitowane w momencie ich wystąpienia, ale powstrzyma ją od ponownej synchronizacji, więc jeśli jeden plik ma dodatkową linię, kolejne porównania linii mogą się nie powieść, nawet jeśli pliki są identyczne (dopóki nie pojawi się kompensacja dodatkowa linia w drugim pliku, wyrównując w ten sposób pasujące linie). Jednak PowerShell jest niezwykle wszechstronny, a przydatne porównanie plików można wykonać, korzystając z tej funkcji, aczkolwiek kosztem znacznej złożoności i pewnych ograniczeń dotyczących zawartości plików. Jeśli chcesz porównać pliki tekstowe z długimi (> 127 znaków) liniami i których linie w większości pasują do 1:
gdzie xx jest długością najdłuższej linii + 9
Wyjaśnienie
(gc file | % -begin { $ln=0 } -process { '{0,6}<<:{1}' -f ++$ln,$_ })
pobiera zawartość pliku i wstawia numer linii i wskaźnik pliku (<< lub >>) do każdej linii (używając operatora ciągu formatu) przed przekazaniem jej do pliku diff.-property { $_.substring(9) }
każe diffowi porównać każdą parę obiektów (ciągów znaków) ignorując pierwsze 9 znaków (które są numerem linii i wskaźnikiem pliku). Wykorzystuje to możliwość określenia obliczonej właściwości (wartości bloku skryptu) zamiast nazwy właściwości.-passthru
powoduje, że diff wypisuje różne obiekty wejściowe (które obejmują numer linii i wskaźnik pliku) zamiast różnych porównywanych obiektów (które nie).sort-object
następnie ustawia wszystkie linie z powrotem w sekwencji.out-string zatrzymuje domyślne obcięcie wyjścia w celu dopasowania do szerokości ekranu (jak zauważył Marc Towersap) przez określenie szerokości wystarczająco dużej, aby uniknąć obcięcia. Zwykle dane wyjściowe byłyby umieszczane w pliku, który jest następnie przeglądany za pomocą przewijanego edytora (np. Notatnika).
Uwaga
Format numeru linii {0,6} daje wyrównany do prawej 6-znakowy numer wiersza (do sortowania). Jeśli pliki mają więcej niż 999,999 wierszy, po prostu zmień format na szerszy. Wymaga to również zmiany
$_.substring
parametru (3 więcej niż szerokość numeru linii) i wartości x-out-string (maksymalna długość linii +$_.substring
parametr).źródło