HADOOP-7286. Refactor the du/dus/df commands to conform to new FsCommand class. Contributed by Daryn Sharp.
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1103968 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
4d205d50f6
commit
b04fb035ec
|
@ -158,6 +158,9 @@ Trunk (unreleased changes)
|
||||||
|
|
||||||
HADOOP-7291. Update Hudson job not to run test-contrib. (Nigel Daley via eli)
|
HADOOP-7291. Update Hudson job not to run test-contrib. (Nigel Daley via eli)
|
||||||
|
|
||||||
|
HADOOP-7286. Refactor the du/dus/df commands to conform to new FsCommand
|
||||||
|
class. (Daryn Sharp via todd)
|
||||||
|
|
||||||
OPTIMIZATIONS
|
OPTIMIZATIONS
|
||||||
|
|
||||||
BUG FIXES
|
BUG FIXES
|
||||||
|
|
|
@ -38,7 +38,6 @@ import org.apache.hadoop.fs.shell.Command;
|
||||||
import org.apache.hadoop.fs.shell.CommandFactory;
|
import org.apache.hadoop.fs.shell.CommandFactory;
|
||||||
import org.apache.hadoop.fs.shell.CommandFormat;
|
import org.apache.hadoop.fs.shell.CommandFormat;
|
||||||
import org.apache.hadoop.fs.shell.FsCommand;
|
import org.apache.hadoop.fs.shell.FsCommand;
|
||||||
import org.apache.hadoop.fs.shell.PathData;
|
|
||||||
import org.apache.hadoop.fs.shell.PathExceptions.PathNotFoundException;
|
import org.apache.hadoop.fs.shell.PathExceptions.PathNotFoundException;
|
||||||
import org.apache.hadoop.io.IOUtils;
|
import org.apache.hadoop.io.IOUtils;
|
||||||
import org.apache.hadoop.ipc.RPC;
|
import org.apache.hadoop.ipc.RPC;
|
||||||
|
@ -64,7 +63,6 @@ public class FsShell extends Configured implements Tool {
|
||||||
static final String GET_SHORT_USAGE = "-get [-ignoreCrc] [-crc] <src> <localdst>";
|
static final String GET_SHORT_USAGE = "-get [-ignoreCrc] [-crc] <src> <localdst>";
|
||||||
static final String COPYTOLOCAL_SHORT_USAGE = GET_SHORT_USAGE.replace(
|
static final String COPYTOLOCAL_SHORT_USAGE = GET_SHORT_USAGE.replace(
|
||||||
"-get", "-copyToLocal");
|
"-get", "-copyToLocal");
|
||||||
static final String DU_USAGE="-du [-s] [-h] <paths...>";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
|
@ -310,128 +308,6 @@ public class FsShell extends Configured implements Tool {
|
||||||
System.err.println("Option '-moveToLocal' is not implemented yet.");
|
System.err.println("Option '-moveToLocal' is not implemented yet.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the size of a partition in the filesystem that contains
|
|
||||||
* the specified <i>path</i>.
|
|
||||||
* @param path a path specifying the source partition. null means /.
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
void df(String path) throws IOException {
|
|
||||||
if (path == null) path = "/";
|
|
||||||
final Path srcPath = new Path(path);
|
|
||||||
final FileSystem srcFs = srcPath.getFileSystem(getConf());
|
|
||||||
if (! srcFs.exists(srcPath)) {
|
|
||||||
throw new PathNotFoundException(path);
|
|
||||||
}
|
|
||||||
final FsStatus stats = srcFs.getStatus(srcPath);
|
|
||||||
final int PercentUsed = (int)(100.0f * (float)stats.getUsed() / (float)stats.getCapacity());
|
|
||||||
System.out.println("Filesystem\t\tSize\tUsed\tAvail\tUse%");
|
|
||||||
System.out.printf("%s\t\t%d\t%d\t%d\t%d%%\n",
|
|
||||||
path,
|
|
||||||
stats.getCapacity(), stats.getUsed(), stats.getRemaining(),
|
|
||||||
PercentUsed);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the size of all files that match the file pattern <i>src</i>
|
|
||||||
* @param cmd
|
|
||||||
* @param pos ignore anything before this pos in cmd
|
|
||||||
* @throws IOException
|
|
||||||
* @see org.apache.hadoop.fs.FileSystem#globStatus(Path)
|
|
||||||
*/
|
|
||||||
void du(String[] cmd, int pos) throws IOException {
|
|
||||||
CommandFormat c = new CommandFormat(
|
|
||||||
"du", 0, Integer.MAX_VALUE, "h", "s");
|
|
||||||
List<String> params;
|
|
||||||
try {
|
|
||||||
params = c.parse(cmd, pos);
|
|
||||||
} catch (IllegalArgumentException iae) {
|
|
||||||
System.err.println("Usage: java FsShell " + DU_USAGE);
|
|
||||||
throw iae;
|
|
||||||
}
|
|
||||||
boolean humanReadable = c.getOpt("h");
|
|
||||||
boolean summary = c.getOpt("s");
|
|
||||||
|
|
||||||
// Default to cwd
|
|
||||||
if (params.isEmpty()) {
|
|
||||||
params.add(".");
|
|
||||||
}
|
|
||||||
|
|
||||||
List<UsagePair> usages = new ArrayList<UsagePair>();
|
|
||||||
|
|
||||||
for (String src : params) {
|
|
||||||
Path srcPath = new Path(src);
|
|
||||||
FileSystem srcFs = srcPath.getFileSystem(getConf());
|
|
||||||
FileStatus globStatus[] = srcFs.globStatus(srcPath);
|
|
||||||
FileStatus statusToPrint[];
|
|
||||||
|
|
||||||
if (summary) {
|
|
||||||
statusToPrint = globStatus;
|
|
||||||
} else {
|
|
||||||
Path statPaths[] = FileUtil.stat2Paths(globStatus, srcPath);
|
|
||||||
try {
|
|
||||||
statusToPrint = srcFs.listStatus(statPaths);
|
|
||||||
} catch(FileNotFoundException fnfe) {
|
|
||||||
statusToPrint = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((statusToPrint == null) || ((statusToPrint.length == 0) &&
|
|
||||||
(!srcFs.exists(srcPath)))){
|
|
||||||
throw new PathNotFoundException(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!summary) {
|
|
||||||
System.out.println("Found " + statusToPrint.length + " items");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (FileStatus stat : statusToPrint) {
|
|
||||||
long length;
|
|
||||||
if (summary || stat.isDirectory()) {
|
|
||||||
length = srcFs.getContentSummary(stat.getPath()).getLength();
|
|
||||||
} else {
|
|
||||||
length = stat.getLen();
|
|
||||||
}
|
|
||||||
|
|
||||||
usages.add(new UsagePair(String.valueOf(stat.getPath()), length));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printUsageSummary(usages, humanReadable);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the summary disk usage of each dir/file
|
|
||||||
* that matches the file pattern <i>src</i>
|
|
||||||
* @param cmd
|
|
||||||
* @param pos ignore anything before this pos in cmd
|
|
||||||
* @throws IOException
|
|
||||||
* @see org.apache.hadoop.fs.FileSystem#globStatus(Path)
|
|
||||||
*/
|
|
||||||
void dus(String[] cmd, int pos) throws IOException {
|
|
||||||
String newcmd[] = new String[cmd.length + 1];
|
|
||||||
System.arraycopy(cmd, 0, newcmd, 0, cmd.length);
|
|
||||||
newcmd[cmd.length] = "-s";
|
|
||||||
du(newcmd, pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void printUsageSummary(List<UsagePair> usages,
|
|
||||||
boolean humanReadable) {
|
|
||||||
int maxColumnWidth = 0;
|
|
||||||
for (UsagePair usage : usages) {
|
|
||||||
String toPrint = humanReadable ?
|
|
||||||
StringUtils.humanReadableInt(usage.bytes) : String.valueOf(usage.bytes);
|
|
||||||
if (toPrint.length() > maxColumnWidth) {
|
|
||||||
maxColumnWidth = toPrint.length();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (UsagePair usage : usages) {
|
|
||||||
String toPrint = humanReadable ?
|
|
||||||
StringUtils.humanReadableInt(usage.bytes) : String.valueOf(usage.bytes);
|
|
||||||
System.out.printf("%-"+ (maxColumnWidth + BORDER) +"s", toPrint);
|
|
||||||
System.out.println(usage.path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Move files that match the file pattern <i>srcf</i>
|
* Move files that match the file pattern <i>srcf</i>
|
||||||
* to a destination file.
|
* to a destination file.
|
||||||
|
@ -639,8 +515,8 @@ public class FsShell extends Configured implements Tool {
|
||||||
String summary = "hadoop fs is the command to execute fs commands. " +
|
String summary = "hadoop fs is the command to execute fs commands. " +
|
||||||
"The full syntax is: \n\n" +
|
"The full syntax is: \n\n" +
|
||||||
"hadoop fs [-fs <local | file system URI>] [-conf <configuration file>]\n\t" +
|
"hadoop fs [-fs <local | file system URI>] [-conf <configuration file>]\n\t" +
|
||||||
"[-D <property=value>] [-df [<path>]] [-du [-s] [-h] <path>]\n\t" +
|
"[-D <property=value>]\n\t" +
|
||||||
"[-dus <path>] [-mv <src> <dst>] [-cp <src> <dst>]\n\t" +
|
"[-mv <src> <dst>] [-cp <src> <dst>]\n\t" +
|
||||||
"[-put <localsrc> ... <dst>] [-copyFromLocal <localsrc> ... <dst>]\n\t" +
|
"[-put <localsrc> ... <dst>] [-copyFromLocal <localsrc> ... <dst>]\n\t" +
|
||||||
"[-moveFromLocal <localsrc> ... <dst>] [" +
|
"[-moveFromLocal <localsrc> ... <dst>] [" +
|
||||||
GET_SHORT_USAGE + "\n\t" +
|
GET_SHORT_USAGE + "\n\t" +
|
||||||
|
@ -662,25 +538,6 @@ public class FsShell extends Configured implements Tool {
|
||||||
"\t\tappear first on the command line. Exactly one additional\n" +
|
"\t\tappear first on the command line. Exactly one additional\n" +
|
||||||
"\t\targument must be specified. \n";
|
"\t\targument must be specified. \n";
|
||||||
|
|
||||||
String df = "-df [<path>]: \tShows the capacity, free and used space of the filesystem.\n"+
|
|
||||||
"\t\tIf the filesystem has multiple partitions, and no path to a particular partition\n"+
|
|
||||||
"\t\tis specified, then the status of the root partitions will be shown.\n";
|
|
||||||
|
|
||||||
String du = "-du [-s] [-h] <path>: \tShow the amount of space, in bytes, used by the files that \n" +
|
|
||||||
"\t\tmatch the specified file pattern. The following flags are optional:\n" +
|
|
||||||
"\t\t -s Rather than showing the size of each individual file that\n" +
|
|
||||||
"\t\t matches the pattern, shows the total (summary) size.\n" +
|
|
||||||
"\t\t -h Formats the sizes of files in a human-readable fashion\n" +
|
|
||||||
"\t\t rather than a number of bytes.\n" +
|
|
||||||
"\n" +
|
|
||||||
"\t\tNote that, even without the -s option, this only shows size summaries\n" +
|
|
||||||
"\t\tone level deep into a directory.\n" +
|
|
||||||
"\t\tThe output is in the form \n" +
|
|
||||||
"\t\t\tsize\tname(full path)\n";
|
|
||||||
|
|
||||||
String dus = "-dus <path>: \tShow the amount of space, in bytes, used by the files that \n" +
|
|
||||||
"\t\tmatch the specified file pattern. This is equivalent to -du -s above.\n";
|
|
||||||
|
|
||||||
String mv = "-mv <src> <dst>: Move files that match the specified file pattern <src>\n" +
|
String mv = "-mv <src> <dst>: Move files that match the specified file pattern <src>\n" +
|
||||||
"\t\tto a destination <dst>. When moving multiple files, the \n" +
|
"\t\tto a destination <dst>. When moving multiple files, the \n" +
|
||||||
"\t\tdestination must be a directory. \n";
|
"\t\tdestination must be a directory. \n";
|
||||||
|
@ -720,12 +577,6 @@ public class FsShell extends Configured implements Tool {
|
||||||
System.out.println(conf);
|
System.out.println(conf);
|
||||||
} else if ("D".equals(cmd)) {
|
} else if ("D".equals(cmd)) {
|
||||||
System.out.println(D);
|
System.out.println(D);
|
||||||
} else if ("df".equals(cmd)) {
|
|
||||||
System.out.println(df);
|
|
||||||
} else if ("du".equals(cmd)) {
|
|
||||||
System.out.println(du);
|
|
||||||
} else if ("dus".equals(cmd)) {
|
|
||||||
System.out.println(dus);
|
|
||||||
} else if ("mv".equals(cmd)) {
|
} else if ("mv".equals(cmd)) {
|
||||||
System.out.println(mv);
|
System.out.println(mv);
|
||||||
} else if ("cp".equals(cmd)) {
|
} else if ("cp".equals(cmd)) {
|
||||||
|
@ -750,14 +601,13 @@ public class FsShell extends Configured implements Tool {
|
||||||
System.out.println(summary);
|
System.out.println(summary);
|
||||||
for (String thisCmdName : commandFactory.getNames()) {
|
for (String thisCmdName : commandFactory.getNames()) {
|
||||||
instance = commandFactory.getInstance(thisCmdName);
|
instance = commandFactory.getInstance(thisCmdName);
|
||||||
System.out.println("\t[" + instance.getUsage() + "]");
|
if (!instance.isDeprecated()) {
|
||||||
|
System.out.println("\t[" + instance.getUsage() + "]");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
System.out.println("\t[-help [cmd]]\n");
|
System.out.println("\t[-help [cmd]]\n");
|
||||||
|
|
||||||
System.out.println(fs);
|
System.out.println(fs);
|
||||||
System.out.println(df);
|
|
||||||
System.out.println(du);
|
|
||||||
System.out.println(dus);
|
|
||||||
System.out.println(mv);
|
System.out.println(mv);
|
||||||
System.out.println(cp);
|
System.out.println(cp);
|
||||||
System.out.println(put);
|
System.out.println(put);
|
||||||
|
@ -768,9 +618,11 @@ public class FsShell extends Configured implements Tool {
|
||||||
System.out.println(moveToLocal);
|
System.out.println(moveToLocal);
|
||||||
|
|
||||||
for (String thisCmdName : commandFactory.getNames()) {
|
for (String thisCmdName : commandFactory.getNames()) {
|
||||||
printHelp(commandFactory.getInstance(thisCmdName));
|
instance = commandFactory.getInstance(thisCmdName);
|
||||||
|
if (!instance.isDeprecated()) {
|
||||||
|
printHelp(instance);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println(help);
|
System.out.println(help);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -791,34 +643,6 @@ public class FsShell extends Configured implements Tool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply operation specified by 'cmd' on all parameters
|
|
||||||
* starting from argv[startindex].
|
|
||||||
*/
|
|
||||||
private int doall(String cmd, String argv[], int startindex) {
|
|
||||||
int exitCode = 0;
|
|
||||||
int i = startindex;
|
|
||||||
|
|
||||||
//
|
|
||||||
// for each source file, issue the command
|
|
||||||
//
|
|
||||||
for (; i < argv.length; i++) {
|
|
||||||
try {
|
|
||||||
//
|
|
||||||
// issue the command to the fs
|
|
||||||
//
|
|
||||||
if ("-df".equals(cmd)) {
|
|
||||||
df(argv[i]);
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
LOG.debug("Error", e);
|
|
||||||
exitCode = -1;
|
|
||||||
displayError(cmd, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return exitCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays format of commands.
|
* Displays format of commands.
|
||||||
*
|
*
|
||||||
|
@ -838,12 +662,6 @@ public class FsShell extends Configured implements Tool {
|
||||||
} else if ("-D".equals(cmd)) {
|
} else if ("-D".equals(cmd)) {
|
||||||
System.err.println("Usage: java FsShell" +
|
System.err.println("Usage: java FsShell" +
|
||||||
" [-D <[property=value>]");
|
" [-D <[property=value>]");
|
||||||
} else if ("-du".equals(cmd) || "-dus".equals(cmd)) {
|
|
||||||
System.err.println("Usage: java FsShell" +
|
|
||||||
" [" + cmd + " <path>]");
|
|
||||||
} else if ("-df".equals(cmd) ) {
|
|
||||||
System.err.println("Usage: java FsShell" +
|
|
||||||
" [" + cmd + " [<path>]]");
|
|
||||||
} else if ("-mv".equals(cmd) || "-cp".equals(cmd)) {
|
} else if ("-mv".equals(cmd) || "-cp".equals(cmd)) {
|
||||||
System.err.println("Usage: java FsShell" +
|
System.err.println("Usage: java FsShell" +
|
||||||
" [" + cmd + " <src> <dst>]");
|
" [" + cmd + " <src> <dst>]");
|
||||||
|
@ -860,9 +678,6 @@ public class FsShell extends Configured implements Tool {
|
||||||
" [" + cmd + " [-crc] <src> <localdst>]");
|
" [" + cmd + " [-crc] <src> <localdst>]");
|
||||||
} else {
|
} else {
|
||||||
System.err.println("Usage: java FsShell");
|
System.err.println("Usage: java FsShell");
|
||||||
System.err.println(" [-df [<path>]]");
|
|
||||||
System.err.println(" [-du [-s] [-h] <path>]");
|
|
||||||
System.err.println(" [-dus <path>]");
|
|
||||||
System.err.println(" [-mv <src> <dst>]");
|
System.err.println(" [-mv <src> <dst>]");
|
||||||
System.err.println(" [-cp <src> <dst>]");
|
System.err.println(" [-cp <src> <dst>]");
|
||||||
System.err.println(" [-put <localsrc> ... <dst>]");
|
System.err.println(" [-put <localsrc> ... <dst>]");
|
||||||
|
@ -872,8 +687,10 @@ public class FsShell extends Configured implements Tool {
|
||||||
System.err.println(" [" + COPYTOLOCAL_SHORT_USAGE + "]");
|
System.err.println(" [" + COPYTOLOCAL_SHORT_USAGE + "]");
|
||||||
System.err.println(" [-moveToLocal [-crc] <src> <localdst>]");
|
System.err.println(" [-moveToLocal [-crc] <src> <localdst>]");
|
||||||
for (String name : commandFactory.getNames()) {
|
for (String name : commandFactory.getNames()) {
|
||||||
instance = commandFactory.getInstance(name);
|
instance = commandFactory.getInstance(name);
|
||||||
System.err.println(" [" + instance.getUsage() + "]");
|
if (!instance.isDeprecated()) {
|
||||||
|
System.err.println(" [" + instance.getUsage() + "]");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
System.err.println(" [-help [cmd]]");
|
System.err.println(" [-help [cmd]]");
|
||||||
System.err.println();
|
System.err.println();
|
||||||
|
@ -967,16 +784,6 @@ public class FsShell extends Configured implements Tool {
|
||||||
exitCode = rename(argv, getConf());
|
exitCode = rename(argv, getConf());
|
||||||
} else if ("-cp".equals(cmd)) {
|
} else if ("-cp".equals(cmd)) {
|
||||||
exitCode = copy(argv, getConf());
|
exitCode = copy(argv, getConf());
|
||||||
} else if ("-df".equals(cmd)) {
|
|
||||||
if (argv.length-1 > 0) {
|
|
||||||
exitCode = doall(cmd, argv, i);
|
|
||||||
} else {
|
|
||||||
df(null);
|
|
||||||
}
|
|
||||||
} else if ("-du".equals(cmd)) {
|
|
||||||
du(argv, i);
|
|
||||||
} else if ("-dus".equals(cmd)) {
|
|
||||||
dus(argv, i);
|
|
||||||
} else if ("-help".equals(cmd)) {
|
} else if ("-help".equals(cmd)) {
|
||||||
if (i < argv.length) {
|
if (i < argv.length) {
|
||||||
printHelp(argv[i]);
|
printHelp(argv[i]);
|
||||||
|
@ -1043,17 +850,4 @@ public class FsShell extends Configured implements Tool {
|
||||||
}
|
}
|
||||||
System.exit(res);
|
System.exit(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility class for a line of du output
|
|
||||||
*/
|
|
||||||
private static class UsagePair {
|
|
||||||
public String path;
|
|
||||||
public long bytes;
|
|
||||||
|
|
||||||
public UsagePair(String path, long bytes) {
|
|
||||||
this.path = path;
|
|
||||||
this.bytes = bytes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,6 +139,10 @@ abstract public class Command extends Configured {
|
||||||
public int run(String...argv) {
|
public int run(String...argv) {
|
||||||
LinkedList<String> args = new LinkedList<String>(Arrays.asList(argv));
|
LinkedList<String> args = new LinkedList<String>(Arrays.asList(argv));
|
||||||
try {
|
try {
|
||||||
|
if (isDeprecated()) {
|
||||||
|
displayWarning(
|
||||||
|
"DEPRECATED: Please use '"+ getReplacementCommand() + "' instead.");
|
||||||
|
}
|
||||||
processOptions(args);
|
processOptions(args);
|
||||||
processArguments(expandArguments(args));
|
processArguments(expandArguments(args));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@ -358,7 +362,7 @@ abstract public class Command extends Configured {
|
||||||
*/
|
*/
|
||||||
public String getUsage() {
|
public String getUsage() {
|
||||||
String cmd = "-" + getCommandName();
|
String cmd = "-" + getCommandName();
|
||||||
String usage = getCommandField("USAGE");
|
String usage = isDeprecated() ? "" : getCommandField("USAGE");
|
||||||
return usage.isEmpty() ? cmd : cmd + " " + usage;
|
return usage.isEmpty() ? cmd : cmd + " " + usage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,7 +371,25 @@ abstract public class Command extends Configured {
|
||||||
* @return text of the usage
|
* @return text of the usage
|
||||||
*/
|
*/
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
return getCommandField("DESCRIPTION");
|
return isDeprecated()
|
||||||
|
? "(DEPRECATED) Same as '" + getReplacementCommand() + "'"
|
||||||
|
: getCommandField("DESCRIPTION");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the command deprecated?
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public final boolean isDeprecated() {
|
||||||
|
return (getReplacementCommand() != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The replacement for a deprecated command
|
||||||
|
* @return null if not deprecated, else alternative command
|
||||||
|
*/
|
||||||
|
public String getReplacementCommand() {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -43,12 +43,13 @@ class Delete extends FsCommand {
|
||||||
/** remove non-directory paths */
|
/** remove non-directory paths */
|
||||||
public static class Rm extends FsCommand {
|
public static class Rm extends FsCommand {
|
||||||
public static final String NAME = "rm";
|
public static final String NAME = "rm";
|
||||||
public static final String USAGE = "[-skipTrash] <src> ...";
|
public static final String USAGE = "[-r|-R] [-skipTrash] <src> ...";
|
||||||
public static final String DESCRIPTION =
|
public static final String DESCRIPTION =
|
||||||
"Delete all files that match the specified file pattern.\n" +
|
"Delete all files that match the specified file pattern.\n" +
|
||||||
"Equivalent to the Unix command \"rm <src>\"\n" +
|
"Equivalent to the Unix command \"rm <src>\"\n" +
|
||||||
"-skipTrash option bypasses trash, if enabled, and immediately\n" +
|
"-skipTrash option bypasses trash, if enabled, and immediately\n" +
|
||||||
"deletes <src>";
|
"deletes <src>\n" +
|
||||||
|
" -[rR] Recursively deletes directories";
|
||||||
|
|
||||||
private boolean skipTrash = false;
|
private boolean skipTrash = false;
|
||||||
private boolean deleteDirs = false;
|
private boolean deleteDirs = false;
|
||||||
|
@ -56,9 +57,9 @@ class Delete extends FsCommand {
|
||||||
@Override
|
@Override
|
||||||
protected void processOptions(LinkedList<String> args) throws IOException {
|
protected void processOptions(LinkedList<String> args) throws IOException {
|
||||||
CommandFormat cf = new CommandFormat(
|
CommandFormat cf = new CommandFormat(
|
||||||
null, 1, Integer.MAX_VALUE, "R", "skipTrash");
|
null, 1, Integer.MAX_VALUE, "r", "R", "skipTrash");
|
||||||
cf.parse(args);
|
cf.parse(args);
|
||||||
deleteDirs = cf.getOpt("R");
|
deleteDirs = cf.getOpt("r") || cf.getOpt("R");
|
||||||
skipTrash = cf.getOpt("skipTrash");
|
skipTrash = cf.getOpt("skipTrash");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,17 +96,16 @@ class Delete extends FsCommand {
|
||||||
/** remove any path */
|
/** remove any path */
|
||||||
static class Rmr extends Rm {
|
static class Rmr extends Rm {
|
||||||
public static final String NAME = "rmr";
|
public static final String NAME = "rmr";
|
||||||
public static final String USAGE = Rm.USAGE;
|
|
||||||
public static final String DESCRIPTION =
|
|
||||||
"Remove all directories which match the specified file\n" +
|
|
||||||
"pattern. Equivalent to the Unix command \"rm -rf <src>\"\n" +
|
|
||||||
"-skipTrash option bypasses trash, if enabled, and immediately\n" +
|
|
||||||
"deletes <src>";
|
|
||||||
|
|
||||||
protected void processOptions(LinkedList<String> args) throws IOException {
|
protected void processOptions(LinkedList<String> args) throws IOException {
|
||||||
args.addFirst("-R");
|
args.addFirst("-r");
|
||||||
super.processOptions(args);
|
super.processOptions(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getReplacementCommand() {
|
||||||
|
return "rm -r";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** empty the trash */
|
/** empty the trash */
|
||||||
|
|
|
@ -48,6 +48,7 @@ abstract public class FsCommand extends Command {
|
||||||
factory.registerCommands(Delete.class);
|
factory.registerCommands(Delete.class);
|
||||||
factory.registerCommands(Display.class);
|
factory.registerCommands(Display.class);
|
||||||
factory.registerCommands(FsShellPermissions.class);
|
factory.registerCommands(FsShellPermissions.class);
|
||||||
|
factory.registerCommands(FsUsage.class);
|
||||||
factory.registerCommands(Ls.class);
|
factory.registerCommands(Ls.class);
|
||||||
factory.registerCommands(Mkdir.class);
|
factory.registerCommands(Mkdir.class);
|
||||||
factory.registerCommands(SetReplication.class);
|
factory.registerCommands(SetReplication.class);
|
||||||
|
|
|
@ -0,0 +1,263 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.hadoop.fs.shell;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.hadoop.classification.InterfaceAudience;
|
||||||
|
import org.apache.hadoop.classification.InterfaceStability;
|
||||||
|
import org.apache.hadoop.fs.FsStatus;
|
||||||
|
import org.apache.hadoop.fs.Path;
|
||||||
|
import org.apache.hadoop.util.StringUtils;
|
||||||
|
|
||||||
|
/** Base class for commands related to viewing filesystem usage, such as
|
||||||
|
* du and df
|
||||||
|
*/
|
||||||
|
@InterfaceAudience.Private
|
||||||
|
@InterfaceStability.Evolving
|
||||||
|
|
||||||
|
class FsUsage extends FsCommand {
|
||||||
|
public static void registerCommands(CommandFactory factory) {
|
||||||
|
factory.addClass(Df.class, "-df");
|
||||||
|
factory.addClass(Du.class, "-du");
|
||||||
|
factory.addClass(Dus.class, "-dus");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean humanReadable = false;
|
||||||
|
protected TableBuilder usagesTable;
|
||||||
|
|
||||||
|
protected String formatSize(long size) {
|
||||||
|
return humanReadable
|
||||||
|
? StringUtils.humanReadableInt(size)
|
||||||
|
: String.valueOf(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Show the size of a partition in the filesystem */
|
||||||
|
public static class Df extends FsUsage {
|
||||||
|
public static final String NAME = "df";
|
||||||
|
public static final String USAGE = "[<path> ...]";
|
||||||
|
public static final String DESCRIPTION =
|
||||||
|
"Shows the capacity, free and used space of the filesystem.\n"+
|
||||||
|
"If the filesystem has multiple partitions, and no path to a\n" +
|
||||||
|
"particular partition is specified, then the status of the root\n" +
|
||||||
|
"partitions will be shown.";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processOptions(LinkedList<String> args)
|
||||||
|
throws IOException {
|
||||||
|
CommandFormat cf = new CommandFormat(null, 0, Integer.MAX_VALUE, "h");
|
||||||
|
cf.parse(args);
|
||||||
|
humanReadable = cf.getOpt("h");
|
||||||
|
if (args.isEmpty()) args.add(Path.SEPARATOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processArguments(LinkedList<PathData> args)
|
||||||
|
throws IOException {
|
||||||
|
usagesTable = new TableBuilder(
|
||||||
|
"Filesystem", "Size", "Used", "Available", "Use%");
|
||||||
|
usagesTable.setRightAlign(1, 2, 3, 4);
|
||||||
|
|
||||||
|
super.processArguments(args);
|
||||||
|
if (!usagesTable.isEmpty()) {
|
||||||
|
usagesTable.printToStream(out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processPath(PathData item) throws IOException {
|
||||||
|
FsStatus fsStats = item.fs.getStatus(item.path);
|
||||||
|
long size = fsStats.getCapacity();
|
||||||
|
long used = fsStats.getUsed();
|
||||||
|
long free = fsStats.getRemaining();
|
||||||
|
|
||||||
|
usagesTable.addRow(
|
||||||
|
item.fs.getUri(),
|
||||||
|
formatSize(size),
|
||||||
|
formatSize(used),
|
||||||
|
formatSize(free),
|
||||||
|
StringUtils.formatPercent((double)used/(double)size, 0)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** show disk usage */
|
||||||
|
public static class Du extends FsUsage {
|
||||||
|
public static final String NAME = "du";
|
||||||
|
public static final String USAGE = "[-s] [-h] <path> ...";
|
||||||
|
public static final String DESCRIPTION =
|
||||||
|
"Show the amount of space, in bytes, used by the files that\n" +
|
||||||
|
"match the specified file pattern. The following flags are optional:\n" +
|
||||||
|
" -s Rather than showing the size of each individual file that\n" +
|
||||||
|
" matches the pattern, shows the total (summary) size.\n" +
|
||||||
|
" -h Formats the sizes of files in a human-readable fashion\n" +
|
||||||
|
" rather than a number of bytes.\n\n" +
|
||||||
|
"Note that, even without the -s option, this only shows size summaries\n" +
|
||||||
|
"one level deep into a directory.\n" +
|
||||||
|
"The output is in the form \n" +
|
||||||
|
"\tsize\tname(full path)\n";
|
||||||
|
|
||||||
|
protected boolean summary = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processOptions(LinkedList<String> args) throws IOException {
|
||||||
|
CommandFormat cf = new CommandFormat(null, 0, Integer.MAX_VALUE, "h", "s");
|
||||||
|
cf.parse(args);
|
||||||
|
humanReadable = cf.getOpt("h");
|
||||||
|
summary = cf.getOpt("s");
|
||||||
|
if (args.isEmpty()) args.add(Path.CUR_DIR);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processPathArgument(PathData item) throws IOException {
|
||||||
|
usagesTable = new TableBuilder(2);
|
||||||
|
// go one level deep on dirs from cmdline unless in summary mode
|
||||||
|
if (!summary && item.stat.isDirectory()) {
|
||||||
|
recursePath(item);
|
||||||
|
} else {
|
||||||
|
super.processPathArgument(item);
|
||||||
|
}
|
||||||
|
usagesTable.printToStream(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processPath(PathData item) throws IOException {
|
||||||
|
long length;
|
||||||
|
if (item.stat.isDirectory()) {
|
||||||
|
length = item.fs.getContentSummary(item.path).getLength();
|
||||||
|
} else {
|
||||||
|
length = item.stat.getLen();
|
||||||
|
}
|
||||||
|
usagesTable.addRow(formatSize(length), item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** show disk usage summary */
|
||||||
|
public static class Dus extends Du {
|
||||||
|
public static final String NAME = "dus";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processOptions(LinkedList<String> args) throws IOException {
|
||||||
|
args.addFirst("-s");
|
||||||
|
super.processOptions(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getReplacementCommand() {
|
||||||
|
return "du -s";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a table of aligned values based on the maximum width of each
|
||||||
|
* column as a string
|
||||||
|
*/
|
||||||
|
private static class TableBuilder {
|
||||||
|
protected boolean hasHeader = false;
|
||||||
|
protected List<String[]> rows;
|
||||||
|
protected int[] widths;
|
||||||
|
protected boolean[] rightAlign;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a table w/o headers
|
||||||
|
* @param columns number of columns
|
||||||
|
*/
|
||||||
|
public TableBuilder(int columns) {
|
||||||
|
rows = new ArrayList<String[]>();
|
||||||
|
widths = new int[columns];
|
||||||
|
rightAlign = new boolean[columns];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a table with headers
|
||||||
|
* @param headers list of headers
|
||||||
|
*/
|
||||||
|
public TableBuilder(Object ... headers) {
|
||||||
|
this(headers.length);
|
||||||
|
this.addRow(headers);
|
||||||
|
hasHeader = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change the default left-align of columns
|
||||||
|
* @param indexes of columns to right align
|
||||||
|
*/
|
||||||
|
public void setRightAlign(int ... indexes) {
|
||||||
|
for (int i : indexes) rightAlign[i] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a row of objects to the table
|
||||||
|
* @param objects the values
|
||||||
|
*/
|
||||||
|
public void addRow(Object ... objects) {
|
||||||
|
String[] row = new String[widths.length];
|
||||||
|
for (int col=0; col < widths.length; col++) {
|
||||||
|
row[col] = String.valueOf(objects[col]);
|
||||||
|
widths[col] = Math.max(widths[col], row[col].length());
|
||||||
|
}
|
||||||
|
rows.add(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the table to a stream
|
||||||
|
* @param out PrintStream for output
|
||||||
|
*/
|
||||||
|
public void printToStream(PrintStream out) {
|
||||||
|
if (isEmpty()) return;
|
||||||
|
|
||||||
|
StringBuilder fmt = new StringBuilder();
|
||||||
|
for (int i=0; i < widths.length; i++) {
|
||||||
|
if (fmt.length() != 0) fmt.append(" ");
|
||||||
|
if (rightAlign[i]) {
|
||||||
|
fmt.append("%"+widths[i]+"s");
|
||||||
|
} else if (i != widths.length-1) {
|
||||||
|
fmt.append("%-"+widths[i]+"s");
|
||||||
|
} else {
|
||||||
|
// prevent trailing spaces if the final column is left-aligned
|
||||||
|
fmt.append("%s");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Object[] row : rows) {
|
||||||
|
out.println(String.format(fmt.toString(), row));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of rows excluding header
|
||||||
|
* @return rows
|
||||||
|
*/
|
||||||
|
public int size() {
|
||||||
|
return rows.size() - (hasHeader ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does table have any rows
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return size() == 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -41,7 +41,7 @@ class Ls extends FsCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String NAME = "ls";
|
public static final String NAME = "ls";
|
||||||
public static final String USAGE = "[<path> ...]";
|
public static final String USAGE = "[-R] [<path> ...]";
|
||||||
public static final String DESCRIPTION =
|
public static final String DESCRIPTION =
|
||||||
"List the contents that match the specified file pattern. If\n" +
|
"List the contents that match the specified file pattern. If\n" +
|
||||||
"path is not specified, the contents of /user/<currentUser>\n" +
|
"path is not specified, the contents of /user/<currentUser>\n" +
|
||||||
|
@ -50,7 +50,8 @@ class Ls extends FsCommand {
|
||||||
"and file entries are of the form \n" +
|
"and file entries are of the form \n" +
|
||||||
"\tfileName(full path) <r n> size \n" +
|
"\tfileName(full path) <r n> size \n" +
|
||||||
"where n is the number of replicas specified for the file \n" +
|
"where n is the number of replicas specified for the file \n" +
|
||||||
"and size is the size of the file, in bytes.";
|
"and size is the size of the file, in bytes.\n" +
|
||||||
|
" -R Recursively list the contents of directories";
|
||||||
|
|
||||||
protected static final SimpleDateFormat dateFormat =
|
protected static final SimpleDateFormat dateFormat =
|
||||||
new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
||||||
|
@ -135,12 +136,6 @@ class Ls extends FsCommand {
|
||||||
*/
|
*/
|
||||||
public static class Lsr extends Ls {
|
public static class Lsr extends Ls {
|
||||||
public static final String NAME = "lsr";
|
public static final String NAME = "lsr";
|
||||||
public static final String USAGE = Ls.USAGE;
|
|
||||||
public static final String DESCRIPTION =
|
|
||||||
"Recursively list the contents that match the specified\n" +
|
|
||||||
"file pattern. Behaves very similarly to hadoop fs -ls,\n" +
|
|
||||||
"except that the data is shown for all the entries in the\n" +
|
|
||||||
"subtree.";
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void processOptions(LinkedList<String> args)
|
protected void processOptions(LinkedList<String> args)
|
||||||
|
@ -148,5 +143,10 @@ class Ls extends FsCommand {
|
||||||
args.addFirst("-R");
|
args.addFirst("-R");
|
||||||
super.processOptions(args);
|
super.processOptions(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getReplacementCommand() {
|
||||||
|
return "ls -R";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,7 +93,7 @@ class Stat extends FsCommand {
|
||||||
: (stat.isFile() ? "regular file" : "symlink"));
|
: (stat.isFile() ? "regular file" : "symlink"));
|
||||||
break;
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
buf.append(item);
|
buf.append(item.path.getName());
|
||||||
break;
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
buf.append(stat.getBlockSize());
|
buf.append(stat.getBlockSize());
|
||||||
|
|
|
@ -54,7 +54,7 @@
|
||||||
<comparators>
|
<comparators>
|
||||||
<comparator>
|
<comparator>
|
||||||
<type>RegexpComparator</type>
|
<type>RegexpComparator</type>
|
||||||
<expected-output>^-ls \[<path> \.\.\.\]:( |\t)*List the contents that match the specified file pattern. If( )*</expected-output>
|
<expected-output>^-ls \[-R\] \[<path> \.\.\.\]:( |\t)*List the contents that match the specified file pattern. If( )*</expected-output>
|
||||||
</comparator>
|
</comparator>
|
||||||
<comparator>
|
<comparator>
|
||||||
<type>RegexpComparator</type>
|
<type>RegexpComparator</type>
|
||||||
|
@ -101,19 +101,7 @@
|
||||||
<comparators>
|
<comparators>
|
||||||
<comparator>
|
<comparator>
|
||||||
<type>RegexpComparator</type>
|
<type>RegexpComparator</type>
|
||||||
<expected-output>^-lsr \[<path> \.\.\.\]:( |\t)*Recursively list the contents that match the specified( )*</expected-output>
|
<expected-output>^-lsr:\s+\(DEPRECATED\) Same as 'ls -R'</expected-output>
|
||||||
</comparator>
|
|
||||||
<comparator>
|
|
||||||
<type>RegexpComparator</type>
|
|
||||||
<expected-output>^( |\t)*file pattern.( |\t)*Behaves very similarly to hadoop fs -ls,( )*</expected-output>
|
|
||||||
</comparator>
|
|
||||||
<comparator>
|
|
||||||
<type>RegexpComparator</type>
|
|
||||||
<expected-output>^( |\t)*except that the data is shown for all the entries in the( )*</expected-output>
|
|
||||||
</comparator>
|
|
||||||
<comparator>
|
|
||||||
<type>RegexpComparator</type>
|
|
||||||
<expected-output>^( |\t)*subtree.( )*</expected-output>
|
|
||||||
</comparator>
|
</comparator>
|
||||||
</comparators>
|
</comparators>
|
||||||
</test>
|
</test>
|
||||||
|
@ -152,7 +140,7 @@
|
||||||
<comparators>
|
<comparators>
|
||||||
<comparator>
|
<comparator>
|
||||||
<type>RegexpComparator</type>
|
<type>RegexpComparator</type>
|
||||||
<expected-output>^-du \[-s\] \[-h\] <path>:\s+Show the amount of space, in bytes, used by the files that\s*</expected-output>
|
<expected-output>^-du \[-s\] \[-h\] <path> \.\.\.:\s+Show the amount of space, in bytes, used by the files that\s*</expected-output>
|
||||||
</comparator>
|
</comparator>
|
||||||
<comparator>
|
<comparator>
|
||||||
<type>RegexpComparator</type>
|
<type>RegexpComparator</type>
|
||||||
|
@ -203,11 +191,7 @@
|
||||||
<comparators>
|
<comparators>
|
||||||
<comparator>
|
<comparator>
|
||||||
<type>RegexpComparator</type>
|
<type>RegexpComparator</type>
|
||||||
<expected-output>^-dus <path>:( |\t)*Show the amount of space, in bytes, used by the files that( )*</expected-output>
|
<expected-output>^-dus:\s+\(DEPRECATED\) Same as 'du -s'</expected-output>
|
||||||
</comparator>
|
|
||||||
<comparator>
|
|
||||||
<type>RegexpComparator</type>
|
|
||||||
<expected-output>^( |\t)*match the specified file pattern. This is equivalent to -du -s above.</expected-output>
|
|
||||||
</comparator>
|
</comparator>
|
||||||
</comparators>
|
</comparators>
|
||||||
</test>
|
</test>
|
||||||
|
@ -299,7 +283,7 @@
|
||||||
<comparators>
|
<comparators>
|
||||||
<comparator>
|
<comparator>
|
||||||
<type>RegexpComparator</type>
|
<type>RegexpComparator</type>
|
||||||
<expected-output>^-rm \[-skipTrash\] <src> \.\.\.:( |\t)*Delete all files that match the specified file pattern.( )*</expected-output>
|
<expected-output>^-rm \[-r\|-R\] \[-skipTrash\] <src> \.\.\.:( |\t)*Delete all files that match the specified file pattern.( )*</expected-output>
|
||||||
</comparator>
|
</comparator>
|
||||||
<comparator>
|
<comparator>
|
||||||
<type>RegexpComparator</type>
|
<type>RegexpComparator</type>
|
||||||
|
@ -326,19 +310,7 @@
|
||||||
<comparators>
|
<comparators>
|
||||||
<comparator>
|
<comparator>
|
||||||
<type>RegexpComparator</type>
|
<type>RegexpComparator</type>
|
||||||
<expected-output>^-rmr \[-skipTrash\] <src> \.\.\.:( |\t)*Remove all directories which match the specified file( )*</expected-output>
|
<expected-output>^-rmr:\s+\(DEPRECATED\) Same as 'rm -r'</expected-output>
|
||||||
</comparator>
|
|
||||||
<comparator>
|
|
||||||
<type>RegexpComparator</type>
|
|
||||||
<expected-output>^( |\t)*pattern. Equivalent to the Unix command "rm -rf <src>"( )*</expected-output>
|
|
||||||
</comparator>
|
|
||||||
<comparator>
|
|
||||||
<type>RegexpComparator</type>
|
|
||||||
<expected-output>^( |\t)*-skipTrash option bypasses trash, if enabled, and immediately( )*</expected-output>
|
|
||||||
</comparator>
|
|
||||||
<comparator>
|
|
||||||
<type>RegexpComparator</type>
|
|
||||||
<expected-output>^( |\t)*deletes <src>( )*</expected-output>
|
|
||||||
</comparator>
|
</comparator>
|
||||||
</comparators>
|
</comparators>
|
||||||
</test>
|
</test>
|
||||||
|
|
Loading…
Reference in New Issue