- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Runtime.InteropServices;
- namespace RobvanderWoude
- {
- class Tail
- {
- static int Main( string[] args )
- {
- try
- {
- int numlines = 1;
- string[] lines;
- #region Command Line Parsing
- string filename = string.Empty;
- bool redirected;
- bool set_l = false;
- bool set_input = false;
- foreach ( string arg in args )
- {
- if ( arg[0] == '/' )
- {
- if ( arg.Length > 3 )
- {
- if ( arg.ToUpper( )[1] == 'L' )
- {
- if ( arg[2] != ':' )
- {
- return WriteError( "Invalid argument: " + arg );
- }
- try
- {
- if ( set_l )
- {
- return WriteError( "Duplicate /L argument" );
- }
- else
- {
- numlines = Convert.ToInt32( arg.Substring( 3 ) );
- if ( numlines < 1 )
- {
- return WriteError( "Number of lines must be 1 or greater" );
- }
- set_l = true;
- }
- }
- catch ( FormatException e )
- {
- return WriteError( "Invalid number of lines: " + arg );
- }
- }
- }
- else
- {
- if ( arg == "/?" )
- {
- return WriteError( );
- }
- else
- {
- return WriteError( "Invalid argument: " + arg );
- }
- }
- }
- else
- {
- if ( set_input )
- {
- return WriteError( "Duplicate file argument" );
- }
- else
- {
- if ( File.Exists( arg ) )
- {
- filename = arg;
- }
- else
- {
- return WriteError( "Invalid filename: " + arg );
- }
- set_input = true;
- }
- }
- }
- if ( ConsoleEx.InputRedirected )
- {
- if ( set_input )
- {
- return WriteError( "Use either file name or redirection, not both" );
- }
- else
- {
- set_input = true;
- redirected = true;
- }
- }
- else
- {
- if ( args.Length == 0 )
- {
- return WriteError( );
- }
- redirected = false;
- }
- #endregion Command Line Parsing
- if ( redirected )
- {
- // Read standard input and store the lines in a list
- List<string> alllines = new List<string>( );
- int peek = 0;
- string line;
- do
- {
- line = Console.In.ReadLine( );
- alllines.Add( line );
- peek = Console.In.Peek( );
- } while ( peek != -1 );
- // Convert the list to an array
- lines = alllines.ToArray( );
- }
- else
- {
- // Read the file and store the lines in an array
- lines = File.ReadAllLines( filename );
- }
- // Display the last lines from the array
- int startline = lines.Length - numlines;
- if ( startline < 0 )
- {
- startline = 0;
- }
- for ( int i = startline; i < lines.Length; i++ )
- {
- Console.WriteLine( lines[i] );
- }
- return 0;
- }
- catch ( Exception e )
- {
- return WriteError( e.Message );
- }
- }
- #region Redirection Detection
- // Code to detect redirection by Hans Passant on StackOverflow.com
- // http://stackoverflow.com/questions/3453220/how-to-detect-if-console-in-stdin-has-been-redirected
- public static class ConsoleEx
- {
- public static bool OutputRedirected
- {
- get
- {
- return FileType.Char != GetFileType( GetStdHandle( StdHandle.Stdout ) );
- }
- }
- public static bool InputRedirected
- {
- get
- {
- return FileType.Char != GetFileType( GetStdHandle( StdHandle.Stdin ) );
- }
- }
- public static bool ErrorRedirected
- {
- get
- {
- return FileType.Char != GetFileType( GetStdHandle( StdHandle.Stderr ) );
- }
- }
- // P/Invoke:
- private enum FileType { Unknown, Disk, Char, Pipe };
- private enum StdHandle { Stdin = -10, Stdout = -11, Stderr = -12 };
- [DllImport( "kernel32.dll" )]
- private static extern FileType GetFileType( IntPtr hdl );
- [DllImport( "kernel32.dll" )]
- private static extern IntPtr GetStdHandle( StdHandle std );
- }
- #endregion Redirection Detection
- #region Error Handling
- public static int WriteError( Exception e = null )
- {
- return WriteError( e == null ? null : e.Message );
- }
- public static int WriteError( string errorMessage )
- {
- if ( string.IsNullOrEmpty( errorMessage ) == false )
- {
- Console.Error.WriteLine( );
- Console.ForegroundColor = ConsoleColor.Red;
- Console.Error.Write( "ERROR: " );
- Console.ForegroundColor = ConsoleColor.White;
- Console.Error.WriteLine( errorMessage );
- Console.ResetColor( );
- }
- /*
- Tail, Version 1.00
- Return the specified number of lines from the end of the specified file
- Usage: TAIL filename [ option ]
- or: TAIL [ option ] < filename
- or: command | TAIL [ option ]
- Where: filename is the optional file to be read
- command is the optional command whose output is to be read
- /L:n read the last n Lines (default: 1 line)
- Examples:
- TAIL filename read the last line (default)
- TAIL /L:2 < filename read the last 2 lines
- command | TAIL /L:5 read the last 5 lines
- Check for redirection by Hans Passant on StackOverflow.com
- /questions/3453220/how-to-detect-if-console-in-stdin-has-been-redirected
- Written by Rob van der Woude
- */
- Console.Error.WriteLine( );
- Console.Error.WriteLine( "Tail, Version 1.00" );
- Console.Error.WriteLine( "Return the specified number of lines from the end of the specified file" );
- Console.Error.WriteLine( );
- Console.Error.Write( "Usage: " );
- Console.ForegroundColor = ConsoleColor.White;
- Console.Error.WriteLine( "TAIL filename [ option ]" );
- Console.ResetColor( );
- Console.Error.Write( " or: " );
- Console.ForegroundColor = ConsoleColor.White;
- Console.Error.WriteLine( "TAIL [ option ] < filename" );
- Console.ResetColor( );
- Console.Error.Write( " or: " );
- Console.ForegroundColor = ConsoleColor.White;
- Console.Error.WriteLine( "command | TAIL [ option ]" );
- Console.ResetColor( );
- Console.Error.WriteLine( );
- Console.Error.Write( "Where: " );
- Console.ForegroundColor = ConsoleColor.White;
- Console.Error.Write( "filename" );
- Console.ResetColor( );
- Console.Error.WriteLine( " is the optional file to be read" );
- Console.ForegroundColor = ConsoleColor.White;
- Console.Error.Write( " command" );
- Console.ResetColor( );
- Console.Error.WriteLine( " is the optional command whose output is to be read" );
- Console.ForegroundColor = ConsoleColor.White;
- Console.Error.Write( " /L:n" );
- Console.ResetColor( );
- Console.Error.Write( " read the last " );
- Console.ForegroundColor = ConsoleColor.White;
- Console.Error.Write( "n L" );
- Console.ResetColor( );
- Console.Error.WriteLine( "ines (default: 1 line)" );
- Console.Error.WriteLine( );
- Console.Error.WriteLine( "Examples:" );
- Console.Error.WriteLine( "TAIL filename read the last line (default)" );
- Console.Error.WriteLine( "TAIL /L:2 < filename read the last 2 lines" );
- Console.Error.WriteLine( "command | TAIL /L:5 read the last 5 lines" );
- Console.Error.WriteLine( );
- Console.Error.Write( "Check for redirection by Hans Passant on " );
- Console.ForegroundColor = ConsoleColor.DarkGray;
- Console.Error.WriteLine( "StackOverflow.com" );
- Console.Error.WriteLine( "/questions/3453220/how-to-detect-if-console-in-stdin-has-been-redirected" );
- Console.ResetColor( );
- Console.Error.WriteLine( );
- Console.Error.WriteLine( "Written by Rob van der Woude" );
- return 1;
- }
- #endregion Error Handling
- }
- }
- //该片段来自于http://www.codesnippet.cn/detail/190820135211.html
来源: http://www.codesnippet.cn/detail/190820135211.html