Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Implement -print0 (separate path names with NUL character).
Signed-off-by: Pierre-Alexandre Meyer <pierre@mouraf.org>
  • Loading branch information
pierre committed Sep 28, 2010
1 parent 3cefb50 commit 667d2a1
Show file tree
Hide file tree
Showing 10 changed files with 193 additions and 19 deletions.
11 changes: 8 additions & 3 deletions src/main/java/com/ning/hfind/Find.java
Expand Up @@ -89,6 +89,7 @@ public class Find

// Extra, non POSIX, primaries
options.addOption("empty", null, false, "True if the current file or directory is empty");
options.addOption("print0", null, false, "This primary always evaluates to true. It prints the pathname of the current file to standard output, followed by an ASCII NUL character (character code 0)");
}

public static void usage()
Expand Down Expand Up @@ -116,6 +117,8 @@ private static void connectToHDFS() throws IOException

public static void main(String[] origArgs) throws ParseException, IOException
{
PrinterConfig config = new PrinterConfig();

CommandLineParser parser = new PosixParser();
CommandLine line = parser.parse(options, origArgs);
String[] args = line.getArgs();
Expand All @@ -138,9 +141,11 @@ public static void main(String[] origArgs) throws ParseException, IOException
String depthOptionValue = line.getOptionValue("depth");
depth = Integer.valueOf(depthOptionValue);
}
boolean depthMode = false;
if (line.hasOption("d")) {
depthMode = true;
config.setDepthMode(true);
}
if (line.hasOption("print0")) {
config.setEndLineWithNull(true);
}

// Ignore certain primaries
Expand All @@ -158,7 +163,7 @@ public static void main(String[] origArgs) throws ParseException, IOException

try {
connectToHDFS();
expression.run(path, fs, depth, depthMode);
expression.run(path, fs, depth, config);

System.exit(0);
}
Expand Down
16 changes: 16 additions & 0 deletions src/main/java/com/ning/hfind/FsItem.java
@@ -0,0 +1,16 @@
package com.ning.hfind;

import com.google.common.collect.ImmutableList;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;

public interface FsItem
{
ImmutableList<FsItem> getChildren();

String getName();

FileStatus getStatus();

FileSystem getFs();
}
12 changes: 8 additions & 4 deletions src/main/java/com/ning/hfind/HdfsItem.java
Expand Up @@ -24,7 +24,7 @@

import java.io.IOException;

public class HdfsItem
public class HdfsItem implements FsItem
{
private final static Logger log = Logger.getLogger(HdfsItem.class.getName());

Expand All @@ -36,7 +36,7 @@ public class HdfsItem

private final String name;

private volatile ImmutableList<HdfsItem> children;
private volatile ImmutableList<FsItem> children;

public HdfsItem(FileSystem fs, String path, int depth) throws IOException
{
Expand All @@ -60,13 +60,14 @@ private HdfsItem(FileSystem fs, FileStatus status, int depth) throws IOException
}
}

public ImmutableList<HdfsItem> getChildren()
@Override
public ImmutableList<FsItem> getChildren()
{
if (depth <= 0) {
children = ImmutableList.of();
}
else if (children == null) {
ImmutableList.Builder<HdfsItem> children = ImmutableList.builder();
ImmutableList.Builder<FsItem> children = ImmutableList.builder();

try {
for (FileStatus status : fs.listStatus(path)) {
Expand All @@ -83,16 +84,19 @@ else if (children == null) {
return children;
}

@Override
public String getName()
{
return name;
}

@Override
public FileStatus getStatus()
{
return status;
}

@Override
public FileSystem getFs()
{
return fs;
Expand Down
41 changes: 33 additions & 8 deletions src/main/java/com/ning/hfind/Printer.java
Expand Up @@ -20,32 +20,57 @@

public class Printer
{
private final FsItem item;
private final Expression expression;
private final boolean depthMode;
private final boolean endLineWithNull;

public Printer(HdfsItem item, Expression expression, boolean depthMode)
public Printer(FsItem item, Expression expression, PrinterConfig config)
{
this.depthMode = depthMode;
run(item, expression);
this.item = item;
this.expression = expression;
this.depthMode = config.depthMode();
this.endLineWithNull = config.endLineWithNull();
}

private void run(HdfsItem item, Expression expression)
public void run()
{
run(item);
}

private void run(FsItem item)
{
FileStatusAttributes itemAttributes = new FileStatusAttributes(item.getFs(), item.getStatus());

String pathName = item.getName();
if (endLineWithNull) {
pathName = String.format("%s\0", pathName);
}

if (!depthMode) {
if (expression.evaluate(itemAttributes)) {
System.out.println(item.getName());
print(pathName, endLineWithNull);
}
}

for (HdfsItem childItem : item.getChildren()) {
run(childItem, expression);
for (FsItem childItem : item.getChildren()) {
run(childItem);
}

if (depthMode) {
if (expression.evaluate(itemAttributes)) {
System.out.println(item.getName());
print(pathName, endLineWithNull);
}
}
}

protected void print(String pathName, boolean dontAddANewLine)
{
if (dontAddANewLine) {
System.out.print(pathName);
}
else {
System.out.println(pathName);
}
}
}
27 changes: 27 additions & 0 deletions src/main/java/com/ning/hfind/PrinterConfig.java
@@ -0,0 +1,27 @@
package com.ning.hfind;

public class PrinterConfig
{
private boolean depthMode = false;
private boolean endLineWithNull = false;

public boolean depthMode()
{
return depthMode;
}

public void setDepthMode(boolean depthMode)
{
this.depthMode = depthMode;
}

public boolean endLineWithNull()
{
return endLineWithNull;
}

public void setEndLineWithNull(boolean endLineWithNull)
{
this.endLineWithNull = endLineWithNull;
}
}
11 changes: 8 additions & 3 deletions src/main/java/com/ning/hfind/primary/Expression.java
Expand Up @@ -17,8 +17,10 @@
package com.ning.hfind.primary;

import com.ning.hfind.FileAttributes;
import com.ning.hfind.FsItem;
import com.ning.hfind.HdfsItem;
import com.ning.hfind.Printer;
import com.ning.hfind.PrinterConfig;
import org.apache.hadoop.fs.FileSystem;

import java.io.IOException;
Expand All @@ -40,6 +42,8 @@ public class Expression

private final Operand operand;

public static final Expression TRUE = new Expression(Primary.ALWAYS_MATCH, Primary.ALWAYS_MATCH, new AndOperand());

/**
* Base expression
*
Expand Down Expand Up @@ -85,11 +89,12 @@ public Expression(Expression expressionLeft, Expression expressionRight, Operand
this.expressionRight = expressionRight;
}

public void run(String path, FileSystem fs, int depth, boolean depthMode) throws IOException
public void run(String path, FileSystem fs, int depth, PrinterConfig config) throws IOException
{
HdfsItem listing = new HdfsItem(fs, path, depth);
FsItem listing = new HdfsItem(fs, path, depth);
Printer printer = new Printer(listing, this, config);

new Printer(listing, this, depthMode);
printer.run();
}

@Override
Expand Down
Expand Up @@ -29,7 +29,7 @@ public class ExpressionFactory
public static Expression buildExpressionFromCommandLine(PushbackIterator<Option> iterator)
{
if (!iterator.hasNext()) {
return new Expression(Primary.ALWAYS_MATCH, Primary.ALWAYS_MATCH, new AndOperand());
return Expression.TRUE;
}
else {
try {
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/com/ning/hfind/primary/PrimaryFactory.java
Expand Up @@ -75,6 +75,9 @@ else if (primary.equals("d")) {
else if (primary.equals("empty")) {
return new EmptyPrimary();
}
else if (primary.equals("print0")) {
return null;
}
else {
throw new IllegalArgumentException(String.format("Primary %s (argument %s) not implemented", primary, argument));
}
Expand Down
39 changes: 39 additions & 0 deletions src/test/java/com/ning/hfind/StubFsItem.java
@@ -0,0 +1,39 @@
package com.ning.hfind;

import com.google.common.collect.ImmutableList;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;

public class StubFsItem implements FsItem
{
private final String name;

public StubFsItem(String name)
{
this.name = name;
}

@Override
public ImmutableList<FsItem> getChildren()
{
return ImmutableList.of();
}

@Override
public String getName()
{
return name;
}

@Override
public FileStatus getStatus()
{
return null;
}

@Override
public FileSystem getFs()
{
return null;
}
}
50 changes: 50 additions & 0 deletions src/test/java/com/ning/hfind/TestPrinter.java
@@ -0,0 +1,50 @@
package com.ning.hfind;

import com.ning.hfind.primary.Expression;
import org.testng.Assert;
import org.testng.annotations.Test;

public class TestPrinter
{
private static final Character NULL_CHARACTER = '\u0000';

class SilentPrinter extends Printer
{
private String lastPathName = null;

public SilentPrinter(FsItem item, Expression expression, PrinterConfig config)
{
super(item, expression, config);
}

@Override
protected void print(String pathName, boolean ignored)
{
lastPathName = pathName;
}

public String getLastPathName()
{
return lastPathName;
}
}

@Test(groups = "fast")
public void testPrint0() throws Exception
{
PrinterConfig config = new PrinterConfig();
config.setEndLineWithNull(true);

testOneItem("/user/pierre/mouraf.org/", config, NULL_CHARACTER);
testOneItem(String.format("/user/pierre/mouraf.org/%s", NULL_CHARACTER), config, NULL_CHARACTER);
testOneItem(String.format("/user/ pierre %s /mouraf.org/", NULL_CHARACTER), config, NULL_CHARACTER);
}

private void testOneItem(String pathName, PrinterConfig config, Character lastCharacter)
{
SilentPrinter printer = new SilentPrinter(new StubFsItem(pathName), Expression.TRUE, config);
printer.run();

Assert.assertEquals(printer.getLastPathName().charAt(printer.getLastPathName().length() - 1), lastCharacter.charValue());
}
}

0 comments on commit 667d2a1

Please sign in to comment.