All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.unix4j.unix.ls.LsCommand Maven / Gradle / Ivy

There is a newer version: 0.6
Show newest version
package org.unix4j.unix.ls;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.unix4j.command.AbstractCommand;
import org.unix4j.context.ExecutionContext;
import org.unix4j.line.Line;
import org.unix4j.processor.LineProcessor;
import org.unix4j.unix.Ls;
import org.unix4j.util.FileUtil;
import org.unix4j.util.sort.ReverseOrderComparator;

/**
 * Implementation of the {@link Ls ls} command.
 */
class LsCommand extends AbstractCommand {
	public LsCommand(LsArguments arguments) {
		super(Ls.NAME, arguments);
	}
	
	private List getArgumentFiles(ExecutionContext context, LsArguments args) {
		if (args.isFilesSet()) {
			return new ArrayList(Arrays.asList(args.getFiles()));
		} else if (args.isPathsSet()) {
			return FileUtil.expandFiles(context.getCurrentDirectory(), args.getPaths());
		}
		//no input files or paths ==> use just the current directory
		final ArrayList list = new ArrayList(1);
		list.add(context.getCurrentDirectory());
		return list;
	}

	/*package*/ static String getSizeString(LsArguments args, long bytes) {
		if (args.isHumanReadable()) {
			final String units = "BKMG";
			int unit = 0;
			int fraction = 0;
			while (bytes > 1000 && (unit + 1) < units.length()) {
				bytes /= 100;
				fraction = (int) (bytes % 10);
				bytes /= 10;
				unit++;
			}
			if (bytes < 10) {
				return bytes + "." + fraction + units.charAt(unit);
			} else {
				return (bytes < 100 ? " " : "") + bytes + units.charAt(unit);
			}
		}
		return String.valueOf(bytes);
	}
	
	@Override
	public LineProcessor execute(final ExecutionContext context, final LineProcessor output) {
		final LsArguments args = getArguments(context);
		final List files = getArgumentFiles(context, args);
		return new LineProcessor() {
			@Override
			public boolean processLine(Line line) {
				return false;//we ignore all input
			}
			@Override
			public void finish() {
				listFiles(context.getCurrentDirectory(), null, files, output, args);
				output.finish();
			}
		};
	}

	private boolean listFiles(File relativeTo, File parent, List files, LineProcessor output, LsArguments args) {
		final Comparator comparator = getComparator(parent == null ? relativeTo : parent, args);
		final boolean allFiles = args.isAllFiles();
		final boolean longFormat = args.isLongFormat();
		final LsFormatter formatter = longFormat ? LsFormatterLong.FACTORY.create(relativeTo, parent, files, args) : LsFormatterShort.INSTANCE;

		//add special directories . and ..
		if (parent != null && allFiles) {
			//add special directories . and ..
			files.add(parent);
			final File grandParent = parent.getAbsoluteFile().getParentFile();
			if (grandParent != null) {
				files.add(grandParent);
			}
		}
		
		//sort files
		Collections.sort(files, comparator);
		
		//print directory header
		if (parent != null) {
			final LsFormatter dirHeaderFmt = LsFormatterDirectoryHeader.FACTORY.create(relativeTo, parent, files, args);
			if (!dirHeaderFmt.writeFormatted(relativeTo, parent, args, output)) {
				return false;
			}
		}
		//print directory files and recurse if necessary
		for (File file : files) {
			if (allFiles || !file.isHidden()) {
				if (file.isDirectory() && parent == null && !args.isRecurseSubdirs()) {
					if (!listFiles(relativeTo, file, FileUtil.toList(file.listFiles()), output, args)) {
						return false;
					}
				} else {
					if (!file.isDirectory() || parent != null) {
						if (!formatter.writeFormatted(parent == null ? relativeTo : parent, file, args, output)) {
							return false;
						}
					}
				}
			}
		}
		
		//recurse subdirs now
		if (args.isRecurseSubdirs()) {
			for (File file : files) {
				if (allFiles || !file.isHidden()) {
					if (file.isDirectory() && (parent == null || !file.equals(parent) && !file.equals(parent.getParentFile()))) {
						if (!listFiles(relativeTo, file, FileUtil.toList(file.listFiles()), output, args)) {
							return false;
						}
					}
				}
			}
		}
		
		return true;//we want more output
	}

	private Comparator getComparator(File relativeTo, LsArguments args) {
		final Comparator comparator = args.isTimeSorted() ? FileComparators.timeAndRelativeFileName(relativeTo) : FileComparators.typeAndRelativeFileName(relativeTo);
		return args.isReverseOrder() ? ReverseOrderComparator.reverse(comparator) : comparator;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy