diff --git a/CHANGES.txt b/CHANGES.txt index 22a5129f56..bf9c4a8e5b 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -158,6 +158,9 @@ Trunk (unreleased changes) 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 BUG FIXES diff --git a/src/java/org/apache/hadoop/fs/FsShell.java b/src/java/org/apache/hadoop/fs/FsShell.java index f58a9604e0..7969bedd96 100644 --- a/src/java/org/apache/hadoop/fs/FsShell.java +++ b/src/java/org/apache/hadoop/fs/FsShell.java @@ -38,7 +38,6 @@ import org.apache.hadoop.fs.shell.CommandFactory; import org.apache.hadoop.fs.shell.CommandFormat; 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.io.IOUtils; 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] "; static final String COPYTOLOCAL_SHORT_USAGE = GET_SHORT_USAGE.replace( "-get", "-copyToLocal"); - static final String DU_USAGE="-du [-s] [-h] "; /** */ @@ -310,128 +308,6 @@ void moveToLocal(String srcf, Path dst) throws IOException { System.err.println("Option '-moveToLocal' is not implemented yet."); } - /** - * Show the size of a partition in the filesystem that contains - * the specified path. - * @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 src - * @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 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 usages = new ArrayList(); - - 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 src - * @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 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 srcf * to a destination file. @@ -639,8 +515,8 @@ private void printHelp(String cmd) { String summary = "hadoop fs is the command to execute fs commands. " + "The full syntax is: \n\n" + "hadoop fs [-fs ] [-conf ]\n\t" + - "[-D ] [-df []] [-du [-s] [-h] ]\n\t" + - "[-dus ] [-mv ] [-cp ]\n\t" + + "[-D ]\n\t" + + "[-mv ] [-cp ]\n\t" + "[-put ... ] [-copyFromLocal ... ]\n\t" + "[-moveFromLocal ... ] [" + GET_SHORT_USAGE + "\n\t" + @@ -662,25 +538,6 @@ private void printHelp(String cmd) { "\t\tappear first on the command line. Exactly one additional\n" + "\t\targument must be specified. \n"; - String df = "-df []: \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] : \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 : \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 : Move files that match the specified file pattern \n" + "\t\tto a destination . When moving multiple files, the \n" + "\t\tdestination must be a directory. \n"; @@ -720,12 +577,6 @@ private void printHelp(String cmd) { System.out.println(conf); } else if ("D".equals(cmd)) { 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)) { System.out.println(mv); } else if ("cp".equals(cmd)) { @@ -750,14 +601,13 @@ private void printHelp(String cmd) { System.out.println(summary); for (String thisCmdName : commandFactory.getNames()) { 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(fs); - System.out.println(df); - System.out.println(du); - System.out.println(dus); System.out.println(mv); System.out.println(cp); System.out.println(put); @@ -768,9 +618,11 @@ private void printHelp(String cmd) { System.out.println(moveToLocal); for (String thisCmdName : commandFactory.getNames()) { - printHelp(commandFactory.getInstance(thisCmdName)); + instance = commandFactory.getInstance(thisCmdName); + if (!instance.isDeprecated()) { + printHelp(instance); + } } - System.out.println(help); } } @@ -791,34 +643,6 @@ private void printHelp(Command instance) { } } - /** - * 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. * @@ -838,12 +662,6 @@ private void printUsage(String cmd) { } else if ("-D".equals(cmd)) { System.err.println("Usage: java FsShell" + " [-D <[property=value>]"); - } else if ("-du".equals(cmd) || "-dus".equals(cmd)) { - System.err.println("Usage: java FsShell" + - " [" + cmd + " ]"); - } else if ("-df".equals(cmd) ) { - System.err.println("Usage: java FsShell" + - " [" + cmd + " []]"); } else if ("-mv".equals(cmd) || "-cp".equals(cmd)) { System.err.println("Usage: java FsShell" + " [" + cmd + " ]"); @@ -860,9 +678,6 @@ private void printUsage(String cmd) { " [" + cmd + " [-crc] ]"); } else { System.err.println("Usage: java FsShell"); - System.err.println(" [-df []]"); - System.err.println(" [-du [-s] [-h] ]"); - System.err.println(" [-dus ]"); System.err.println(" [-mv ]"); System.err.println(" [-cp ]"); System.err.println(" [-put ... ]"); @@ -872,8 +687,10 @@ private void printUsage(String cmd) { System.err.println(" [" + COPYTOLOCAL_SHORT_USAGE + "]"); System.err.println(" [-moveToLocal [-crc] ]"); for (String name : commandFactory.getNames()) { - instance = commandFactory.getInstance(name); - System.err.println(" [" + instance.getUsage() + "]"); + instance = commandFactory.getInstance(name); + if (!instance.isDeprecated()) { + System.err.println(" [" + instance.getUsage() + "]"); + } } System.err.println(" [-help [cmd]]"); System.err.println(); @@ -967,16 +784,6 @@ public int run(String argv[]) throws Exception { exitCode = rename(argv, getConf()); } else if ("-cp".equals(cmd)) { 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)) { if (i < argv.length) { printHelp(argv[i]); @@ -1043,17 +850,4 @@ public static void main(String argv[]) throws Exception { } 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; - } - } } diff --git a/src/java/org/apache/hadoop/fs/shell/Command.java b/src/java/org/apache/hadoop/fs/shell/Command.java index 31dbb59e92..a23c481637 100644 --- a/src/java/org/apache/hadoop/fs/shell/Command.java +++ b/src/java/org/apache/hadoop/fs/shell/Command.java @@ -139,6 +139,10 @@ public int runAll() { public int run(String...argv) { LinkedList args = new LinkedList(Arrays.asList(argv)); try { + if (isDeprecated()) { + displayWarning( + "DEPRECATED: Please use '"+ getReplacementCommand() + "' instead."); + } processOptions(args); processArguments(expandArguments(args)); } catch (IOException e) { @@ -358,7 +362,7 @@ public void displayWarning(String message) { */ public String getUsage() { String cmd = "-" + getCommandName(); - String usage = getCommandField("USAGE"); + String usage = isDeprecated() ? "" : getCommandField("USAGE"); return usage.isEmpty() ? cmd : cmd + " " + usage; } @@ -367,7 +371,25 @@ public String getUsage() { * @return text of the usage */ 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; } /** diff --git a/src/java/org/apache/hadoop/fs/shell/Delete.java b/src/java/org/apache/hadoop/fs/shell/Delete.java index ba3bc8bd28..f33b4793df 100644 --- a/src/java/org/apache/hadoop/fs/shell/Delete.java +++ b/src/java/org/apache/hadoop/fs/shell/Delete.java @@ -43,12 +43,13 @@ public static void registerCommands(CommandFactory factory) { /** remove non-directory paths */ public static class Rm extends FsCommand { public static final String NAME = "rm"; - public static final String USAGE = "[-skipTrash] ..."; + public static final String USAGE = "[-r|-R] [-skipTrash] ..."; public static final String DESCRIPTION = "Delete all files that match the specified file pattern.\n" + "Equivalent to the Unix command \"rm \"\n" + "-skipTrash option bypasses trash, if enabled, and immediately\n" + - "deletes "; + "deletes \n" + + " -[rR] Recursively deletes directories"; private boolean skipTrash = false; private boolean deleteDirs = false; @@ -56,9 +57,9 @@ public static class Rm extends FsCommand { @Override protected void processOptions(LinkedList args) throws IOException { CommandFormat cf = new CommandFormat( - null, 1, Integer.MAX_VALUE, "R", "skipTrash"); + null, 1, Integer.MAX_VALUE, "r", "R", "skipTrash"); cf.parse(args); - deleteDirs = cf.getOpt("R"); + deleteDirs = cf.getOpt("r") || cf.getOpt("R"); skipTrash = cf.getOpt("skipTrash"); } @@ -95,17 +96,16 @@ private boolean moveToTrash(PathData item) throws IOException { /** remove any path */ static class Rmr extends Rm { 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 \"\n" + - "-skipTrash option bypasses trash, if enabled, and immediately\n" + - "deletes "; protected void processOptions(LinkedList args) throws IOException { - args.addFirst("-R"); + args.addFirst("-r"); super.processOptions(args); } + + @Override + public String getReplacementCommand() { + return "rm -r"; + } } /** empty the trash */ diff --git a/src/java/org/apache/hadoop/fs/shell/FsCommand.java b/src/java/org/apache/hadoop/fs/shell/FsCommand.java index 29628ea4a9..507e28ab0a 100644 --- a/src/java/org/apache/hadoop/fs/shell/FsCommand.java +++ b/src/java/org/apache/hadoop/fs/shell/FsCommand.java @@ -48,6 +48,7 @@ public static void registerCommands(CommandFactory factory) { factory.registerCommands(Delete.class); factory.registerCommands(Display.class); factory.registerCommands(FsShellPermissions.class); + factory.registerCommands(FsUsage.class); factory.registerCommands(Ls.class); factory.registerCommands(Mkdir.class); factory.registerCommands(SetReplication.class); diff --git a/src/java/org/apache/hadoop/fs/shell/FsUsage.java b/src/java/org/apache/hadoop/fs/shell/FsUsage.java new file mode 100644 index 0000000000..70d781bc64 --- /dev/null +++ b/src/java/org/apache/hadoop/fs/shell/FsUsage.java @@ -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 = "[ ...]"; + 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 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 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] ..."; + 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 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 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 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(); + 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; + } + } +} \ No newline at end of file diff --git a/src/java/org/apache/hadoop/fs/shell/Ls.java b/src/java/org/apache/hadoop/fs/shell/Ls.java index cb752e2ec0..8eb7c6af5a 100644 --- a/src/java/org/apache/hadoop/fs/shell/Ls.java +++ b/src/java/org/apache/hadoop/fs/shell/Ls.java @@ -41,7 +41,7 @@ public static void registerCommands(CommandFactory factory) { } public static final String NAME = "ls"; - public static final String USAGE = "[ ...]"; + public static final String USAGE = "[-R] [ ...]"; public static final String DESCRIPTION = "List the contents that match the specified file pattern. If\n" + "path is not specified, the contents of /user/\n" + @@ -50,7 +50,8 @@ public static void registerCommands(CommandFactory factory) { "and file entries are of the form \n" + "\tfileName(full path) size \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 = new SimpleDateFormat("yyyy-MM-dd HH:mm"); @@ -135,12 +136,6 @@ private int maxLength(int n, Object value) { */ public static class Lsr extends Ls { 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 protected void processOptions(LinkedList args) @@ -148,5 +143,10 @@ protected void processOptions(LinkedList args) args.addFirst("-R"); super.processOptions(args); } + + @Override + public String getReplacementCommand() { + return "ls -R"; + } } } diff --git a/src/java/org/apache/hadoop/fs/shell/Stat.java b/src/java/org/apache/hadoop/fs/shell/Stat.java index 716fe512a5..6bd57cf5a1 100644 --- a/src/java/org/apache/hadoop/fs/shell/Stat.java +++ b/src/java/org/apache/hadoop/fs/shell/Stat.java @@ -93,7 +93,7 @@ protected void processPath(PathData item) throws IOException { : (stat.isFile() ? "regular file" : "symlink")); break; case 'n': - buf.append(item); + buf.append(item.path.getName()); break; case 'o': buf.append(stat.getBlockSize()); diff --git a/src/test/core/org/apache/hadoop/cli/testConf.xml b/src/test/core/org/apache/hadoop/cli/testConf.xml index 4351f4b3b9..af810f5425 100644 --- a/src/test/core/org/apache/hadoop/cli/testConf.xml +++ b/src/test/core/org/apache/hadoop/cli/testConf.xml @@ -54,7 +54,7 @@ RegexpComparator - ^-ls \[<path> \.\.\.\]:( |\t)*List the contents that match the specified file pattern. If( )* + ^-ls \[-R\] \[<path> \.\.\.\]:( |\t)*List the contents that match the specified file pattern. If( )* RegexpComparator @@ -101,19 +101,7 @@ RegexpComparator - ^-lsr \[<path> \.\.\.\]:( |\t)*Recursively list the contents that match the specified( )* - - - RegexpComparator - ^( |\t)*file pattern.( |\t)*Behaves very similarly to hadoop fs -ls,( )* - - - RegexpComparator - ^( |\t)*except that the data is shown for all the entries in the( )* - - - RegexpComparator - ^( |\t)*subtree.( )* + ^-lsr:\s+\(DEPRECATED\) Same as 'ls -R' @@ -152,7 +140,7 @@ RegexpComparator - ^-du \[-s\] \[-h\] <path>:\s+Show the amount of space, in bytes, used by the files that\s* + ^-du \[-s\] \[-h\] <path> \.\.\.:\s+Show the amount of space, in bytes, used by the files that\s* RegexpComparator @@ -203,11 +191,7 @@ RegexpComparator - ^-dus <path>:( |\t)*Show the amount of space, in bytes, used by the files that( )* - - - RegexpComparator - ^( |\t)*match the specified file pattern. This is equivalent to -du -s above. + ^-dus:\s+\(DEPRECATED\) Same as 'du -s' @@ -299,7 +283,7 @@ RegexpComparator - ^-rm \[-skipTrash\] <src> \.\.\.:( |\t)*Delete all files that match the specified file pattern.( )* + ^-rm \[-r\|-R\] \[-skipTrash\] <src> \.\.\.:( |\t)*Delete all files that match the specified file pattern.( )* RegexpComparator @@ -326,19 +310,7 @@ RegexpComparator - ^-rmr \[-skipTrash\] <src> \.\.\.:( |\t)*Remove all directories which match the specified file( )* - - - RegexpComparator - ^( |\t)*pattern. Equivalent to the Unix command "rm -rf <src>"( )* - - - RegexpComparator - ^( |\t)*-skipTrash option bypasses trash, if enabled, and immediately( )* - - - RegexpComparator - ^( |\t)*deletes <src>( )* + ^-rmr:\s+\(DEPRECATED\) Same as 'rm -r'