Я не знаю, сможете ли вы сделать это с помощью find, но альтернативным решением было бы создать сценарий оболочки и запустить его с помощью find.
lastline.sh:
echo $(tail -1 $1),$1
Сделать сценарий исполняемым
chmod +x lastline.sh
Использовать find
:
find . -name "*.txt" -exec ./lastline.sh {} \;
Это будет работать, если ваш тип Options является структурой, так как вы можете изменить саму структуру.
Если Options - это класс (ссылочный тип), вы не можете назначить текущий экземпляр ссылочного типа в этом экземпляре. Предлагая вам написать вспомогательный класс и поместить туда свои методы Read и Save, как это
public class XmlSerializerHelper<T>
{
public Type _type;
public XmlSerializerHelper()
{
_type = typeof(T);
}
public void Save(string path, object obj)
{
using (TextWriter textWriter = new StreamWriter(path))
{
XmlSerializer serializer = new XmlSerializer(_type);
serializer.Serialize(textWriter, obj);
}
}
public T Read(string path)
{
T result;
using (TextReader textReader = new StreamReader(path))
{
XmlSerializer deserializer = new XmlSerializer(_type);
result = (T)deserializer.Deserialize(textReader);
}
return result;
}
}
А затем использовать его у вызывающего, чтобы читать и сохранять объекты, вместо того, чтобы пробовать это из класса.
//In the caller
var helper=new XmlSerializerHelper<Options>();
var obj=new Options();
//Write and read
helper.Save("yourpath",obj);
obj=helper.Read("yourpath");
И поместите XmlSerializerHelper в пространстве имен Util, он может использоваться повторно и будет работать с любым типом.
Создайте свой метод .Read ()
как статическую функцию, которая возвращает прочитанный объект:
public static Options Read(string path)
{
XmlSerializer deserializer = new XmlSerializer(typeof(Options));
using (TextReader textReader = new StreamReader(path))
{
return (Options)deserializer.Deserialize(textReader);
}
}
Затем измените свой вызывающий код так, а не что-то вроде этого:
Options myOptions = new Options();
myOptions.Read(@"C:\Options.xml");
Вы делаете что-то вроде этого:
Options myOptions = Options.Read(@"C:\Options.xml");
Хорошая разница в том, что невозможно иметь объект Options, за которым не было бы каких-то данных.
Объект не может десериализовать себя по определению: он уже существует, и десериализация создает новый экземпляр типа.
Иногда имеет смысл создать новый пустой экземпляр класса, а затем заполнить его с информацией, полученной из XML. Экземпляр также может быть «почти пустым». Вы можете сделать это, например, для загрузки пользовательских предпочтений или вообще, чтобы вернуть экземпляр в прежнее состояние. «Пустое» или «почти пустое» состояние экземпляра было бы допустимым состоянием для класса: он просто не знал бы, в каком состоянии он находился до того, как он был сохранен.
Кроме того, Я рекомендую вам выработать привычку реализовывать блоки «using»:
public void Save()
{
XmlSerializer serializer = new XmlSerializer(typeof(Options));
using (TextWriter textWriter = new StreamWriter(@"C:\Options.xml"))
{
serializer.Serialize(textWriter, this);
// no longer needed: textWriter.Close();
}
}
public void Read()
{
XmlSerializer deserializer = new XmlSerializer(typeof(Options));
using (TextReader textReader = new StreamReader(@"C:\Options.xml"))
{
// no longer needed: textReader.Close();
}
}
Это гарантирует, что TextReaders будут удалены, даже если будет сгенерировано исключение. Вот почему вызовы Close больше не нужны.
См. Метод XmlSerializer.Deserialize : Вы можете создать статический метод, подобный следующему:
public static Options DeserializeFromFile(string filename) {
// Create an instance of the XmlSerializer specifying type and namespace.
XmlSerializer serializer = new XmlSerializer(typeof(Options));
// A FileStream is needed to read the XML document.
using (FileStream fs = new FileStream(filename, FileMode.Open)) {
XmlReader reader = new XmlTextReader(fs);
return (Options) serializer.Deserialize(reader);
} // using
}
Вышеупомянутое можно вызвать как:
Options foo = Options.DeserializeFromFile(@"C:\Options.xml");
Я выбрал такой подход (в vb)
Public Class SerialisableClass
Public Sub SaveToXML(ByVal outputFilename As String)
Dim xmls = New System.Xml.Serialization.XmlSerializer(Me.GetType)
Using sw = New IO.StreamWriter(outputFilename)
xmls.Serialize(sw, Me)
End Using
End Sub
Private tempState As Object = Me
Public Sub ReadFromXML(ByVal inputFilename As String)
Dim xmls = New System.Xml.Serialization.XmlSerializer(Me.GetType)
Using sr As New IO.StreamReader(inputFilename)
tempState = xmls.Deserialize(sr)
End Using
For Each pi In tempState.GetType.GetProperties()
Dim name = pi.Name
Dim realProp = (From p In Me.GetType.GetProperties
Where p.Name = name And p.MemberType = Reflection.MemberTypes.Property).Take(1)(0)
realProp.SetValue(Me, pi.GetValue(tempState, Nothing), Nothing)
Next
End Sub
End Class
Я могу просто использовать что-то вроде этого:
Public Class ClientSettings
Inherits SerialisableClass
Public Property ZipExePath As String
Public Property DownloadPath As String
Public Property UpdateInstallPath As String
End Class
и вызывать это так:
Dim cs As New ClientSettings
cs.ReadFromXML("c:\myXMLfile.xml")
или даже лучше (если я добавлю необходимый конструктор):
Dim cs as New ClientSettings("c:\myXMLFile.xml")
Мне кажется, это хорошо и чисто и хорошо работает в моей ситуации.
Будьте здоровы