dirmerge (dirmerge), Lektion, Seite 723798
https://www.purl.org/stefan_ram/pub/dirmerge_java (Permalink) ist die kanonische URI dieser Seite.
Stefan Ram

dirmerge

/* Copyright 2010 Stefan Ram.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */

/*

IDENTIFICATION
==============

This is dirmerge, Version 1.0, by Stefan Ram.

INTRODUCTION
============

This is raw experimental untested Software.
Use entirely on your own risk.

This program will merge two directories
into a single directory. It was published first at
2010-10-05. Later versions might be published later
and might be more tested and stable.

INSTALLATION
============

One needs to install the JDK 1.7.0 first and then
compile this program. Get the JDK 1.7.0 from
http://dlc.sun.com.edgesuite.net/jdk7/binaries/index.html
install it and add the bin-directory of the JDK to
the PATH environment variable. Then, compile with
javac Main.java
.

USAGE
=====

To merge source0 and source1, use:

java Main source0 source1 src1

wherein

"source0" is one directory of the two directories
to be merged (also called "target" below). The
contents of this directory will be extended (modified,
similar to a situation where the contents of source1
is copied into source0), but nothing should be deleted.

"source1" is the second source directory. The contents
of this directory will only be read, but not modified.

"src1" is an id text to be used (to rename files, e.g.,
a file "alpha.txt" might be renamed to "alpha(src1).txt",
see below). It could be any text, but should only contain
latin letters and the digits 0-9.

This assumes that "source0" and "source1" is the
relative path of these two directories in relation
to the directory, where "java" was called. (Absolute
paths or longer paths in this commandline should work,
but this has never been tested.)

DEFINITION
==========

To "merge" means:

The above call will copy the contents of the
source1 directory into the source0 directory,
but during this:

- if two subdirectories have the same name,
they will be merged into a single subdirectory
with this name

- if two files have the same name, then:

- if these files have the same contents,
they will be merged into a single file
with this name and this contents

- otherwise the file to be merged will be
renamed to a new name, so that both files
will be retained when they have different
contents, even though the names were the
same.

This new name will be constructed from:

+ the original name of the file

+ the id text given on the command line
(for example, "src1")

+ an additional number, if required, to
obtain a unique file name

This program was written to merge only two sources.
Attempts to merge more than two sources might create
more files than necessary, because files are only compared
to files with exactly the same name, not to renamed files.
So, when a new files contains the same information as a
renamed file, this will not be detected.

EXAMPLE
=======

Given

source0/alpha.txt
source0/beta.txt
source0/delta/

source1/alpha.txt
source1/beta.txt
source1/gamma.txt
source1/delta/

where both alpha.txt files have the same contents,
but both beta.txt files differ, the call

java Main source0 source1 src1

will create this merge

source0/alpha.txt
source0/beta.txt
source0/beta(src1).txt
source0/gamma.txt
source0/delta/

This would also proceed in this mode into any
subdirectories.

REPORT
======

The program now writes a report to both STDERR and
STDOUT, so when STDOUT is being redirected into a log
file, STDERR is still visible on the console:

java Main source0 source1 source1 >log.txt

The log lines written are of the three types as
shown in the following three example lines:

merging file: source0\alpha.txt
creating file: source0\gamma.txt
entering directory: source0\delta

"mergin file" means that the file to be "copied"
was found to have the same name and contents as
an existing file and that, therefore, nothing is
changed.

"creating file" means that a new file is indeed
created, because a file with this name and contents
does not already exist in the target.

"entering directory" means that a directory is
"entered" - which means that the directory is
created, if it was not already there.

WARNING
=======

For security reasons only copies of the original
directories should be used, in the best case, on a
virtual system or with the possibility to undo all
effects of this program. (Since this is untested
experimental software.)

The result of the merge should then be carefully
examined.

*/

public final class Main
{
public static void main( final java.lang.String[] args /* target source sourceid */ )
throws java.lang.Exception
{ mergeContentsOf
( new java.io.File( args[ 1 ]).toPath(), args[ 2 ], new java.io.File( args[ 0 ]).toPath() ); }

public static void mergeContentsOf
( final java.nio.file.Path source,
final java.lang.String description,
final java.nio.file.Path newTarget )
throws java.lang.Exception
{ final java.lang.String methodName = "Main.mergeContentsOf";
final java.nio.file.DirectoryStream<java.nio.file.Path> directoryStream = source.newDirectoryStream( "*" );
try
{ for( final java.nio.file.Path path : directoryStream )
{ merge( path, description, newTarget ); }}
finally
{ directoryStream.close(); }}

public static void merge
( final java.nio.file.Path source,
final java.lang.String description,
final java.nio.file.Path target )
throws java.lang.Exception
{ final java.lang.String methodName = "Main.merge";
final java.lang.String name = lastSegmentOf( source );
if( source.exists() )
{ if( isDirectory( source ) )
{ java.nio.file.Path newTarget;
if( hasEntry( target, name ))
{ newTarget = getEntry( target, name );
if( !isDirectory( newTarget ))
{ if( !isFile( newTarget ))log( "unexpected: corresponding target entry is neither dir nor file." );
newTarget = inventDirectory( target, description, name ); /* make new name until free */ }}
else
{ newTarget = makeDirectory( target, description, name ); }
java.lang.System.out.println( "entering directory: " + newTarget );
java.lang.System.err.println( "entering directory: " + newTarget );
mergeContentsOf( source, description, newTarget ); /* enum each of source */ }
else if( isFile( source ))
{ java.nio.file.Path newTarget; boolean copy = true;
if( hasEntry( target, name ))
{ newTarget = getEntry( target, name );
if( fileEquals( source, newTarget ))copy = false;
else
{ newTarget = inventFile( target, description, name ); }}
else
{ newTarget = makeFile( target, name ); }
if( copy )copyTo( source, newTarget );
else
{ java.lang.System.out.println( "merging file: " + newTarget );
java.lang.System.err.println( "merging file: " + newTarget ); }}
else
{ log( "type of source entry is unknown" ); }}}

public static boolean isDirectory( final java.nio.file.Path path )
throws java.lang.Exception
{ final java.nio.file.attribute.BasicFileAttributes attributes = java.nio.file.attribute.Attributes.readBasicFileAttributes( path );
return attributes.isDirectory(); }

public static boolean isFile( final java.nio.file.Path path )
throws java.lang.Exception
{ final java.nio.file.attribute.BasicFileAttributes attributes = java.nio.file.attribute.Attributes.readBasicFileAttributes( path );
return attributes.isRegularFile(); }

public static java.lang.String lastSegmentOf
( final java.nio.file.Path path )
throws java.lang.Exception
{ final java.lang.String methodName = "Main.lastSegmentOf";
final java.lang.String result = path.getName( path.getNameCount() - 1 ).toString();
return result; }

public static boolean hasEntry
( final java.nio.file.Path directory,
final java.lang.String name )
throws java.lang.Exception
{ return getEntry( directory, name ).exists(); }

public static java.nio.file.Path getEntry
( final java.nio.file.Path directory,
final java.lang.String name )
throws java.lang.Exception
{ return directory.resolve( name ); }

public static void log
( final java.lang.String text )
throws java.lang.Exception
{ java.lang.System.out.println( text );
java.lang.System.err.println( text ); }

public static void verbose
( final java.lang.String text )
throws java.lang.Exception
{ java.lang.System.out.println( text );
java.lang.System.err.println( text );}

public static java.nio.file.Path inventDirectory
( final java.nio.file.Path target,
final java.lang.String description,
final java.lang.String name )
throws java.lang.Exception
{ java.nio.file.Path result = makeDirectory( target, description, makeName( name, description ) );
int i = 0; while( result == null )
{ result = makeDirectory( target, description, makeName( name, description ) ); }
return result; }

public static java.nio.file.Path inventFile
( final java.nio.file.Path path,
final java.lang.String description,
final java.lang.String name )
throws java.lang.Exception
{ java.nio.file.Path result = makeFile( path, makeName( name, description ));
int i = 0; while( result == null )
{ result = makeFile( path, makeName( name, description, ++i )); }
return result; }

public static java.nio.file.Path makeFile
( final java.nio.file.Path path,
final java.lang.String name )
throws java.lang.Exception
{ java.nio.file.Path result = getEntry( path, name );
if( result.exists() )return null;
return result; }

public static java.nio.file.Path makeDirectory
( final java.nio.file.Path target,
final java.lang.String description,
final java.lang.String name )
throws java.lang.Exception
{ java.nio.file.Path result = null;
return getEntry( target, name ).createDirectory( new java.nio.file.attribute.FileAttribute[ 0 ] ); }

public static void mergeContentsOf
( final java.nio.file.Path source,
final java.lang.String description,
final java.nio.file.Path newTarget )
throws java.lang.Exception
{ final java.lang.String methodName = "Main.mergeContentsOf";
final java.nio.file.DirectoryStream<java.nio.file.Path> directoryStream = source.newDirectoryStream( "*" );
try
{ for( final java.nio.file.Path path : directoryStream )
{ merge( path, description, newTarget ); }}
finally
{ directoryStream.close(); }}

public static boolean fileEquals
( final java.nio.file.Path source,
final java.nio.file.Path newTarget )
throws java.lang.Exception
{ final boolean result = equals
( new java.io.File( source.toString() ),
new java.io.File( newTarget.toString() ));
return result; }

public static void copyTo
( final java.nio.file.Path source,
final java.nio.file.Path newTarget )
throws java.lang.Exception
{ final java.lang.String methodName = "Main.copyTo";
java.lang.System.out.println( "creating file: " + newTarget );
java.lang.System.err.println( "creating file: " + newTarget );
source.copyTo( newTarget, java.nio.file.StandardCopyOption.COPY_ATTRIBUTES ); }

public static java.lang.String makeName
( final java.lang.String name,
final java.lang.String description )
throws java.lang.Exception
{ final java.lang.String methodName = "Main.makeName";
final int position = name.lastIndexOf( '.' );
if( position > -1 )
return name.substring( 0, position ) + "(" + description + ")" + name.substring( position );
else
return name + "(" + description + ")"; }

public static java.lang.String makeName
( final java.lang.String name,
final java.lang.String description,
final int i )
throws java.lang.Exception
{ return makeName( name, description + ")(" + i ); }

public static void close( final java.io.Closeable closeable )
{ try { closeable.close(); }
catch( final java.io.IOException iOException )
{ java.lang.System.out.println( iOException ); }}

public static boolean equals /* expects two existing files -- not directories */
( java.io.File targetFile, java.io.File sourceFile )
throws java.lang.Exception
{ final java.io.InputStream target = new java.io.BufferedInputStream( new java.io.FileInputStream( targetFile ));
// final java.nio.channels.SeekableByteChannel target_ = targetFile.toPath().newByteChannel( )); // java.util.EnumSet.of( java.nio.file.OpenOption.READ )
try
{ final java.io.InputStream source = new java.io.BufferedInputStream( new java.io.FileInputStream( sourceFile ));
// final java.nio.channels.SeekableByteChannel source_ = sourceFile.toPath().newByteChannel( )); // java.util.EnumSet.of( java.nio.file.OpenOption.READ )
try
{ while( true )
{ int t = target.read();
int s = source.read();
if( t != s )return false;
if( t == -1 )return true; }}
finally
{ close( source ); }}
finally
{ close( target ); }}}
Aussprachehinweis
close cloz

Seiteninformationen und Impressum   |   Mitteilungsformular  |   "ram@zedat.fu-berlin.de" (ohne die Anführungszeichen) ist die Netzpostadresse von Stefan Ram.   |   Eine Verbindung zur Stefan-Ram-Startseite befindet sich oben auf dieser Seite hinter dem Text "Stefan Ram".)  |   Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram. Schlüsselwörter zu dieser Seite/relevant keywords describing this page: Stefan Ram Berlin slrprd slrprd stefanramberlin spellched stefanram723798 stefan_ram:723798 dirmerge Stefan Ram, Berlin, and, or, near, uni, online, slrprd, slrprdqxx, slrprddoc, slrprd723798, slrprddef723798, PbclevtugFgrsnaEnz Erklärung, Beschreibung, Info, Information, Hinweis,

Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram.
https://www.purl.org/stefan_ram/pub/dirmerge_java