/** * Prompt to confirm that the user wants to delete the JShellItem from the file system. If so, * remove it. If -f is supplied, do not prompt and confirm. If the root directory is specified, * its contents but not itself will be subject to deletion. * * @param paths the JShellItem to be removed. */ public void rm(List<String> paths) throws Exception { // Loop through the user inputs. for (String path : paths) { // Initialize the current JShellItem. JShellItem item = getItemAtPath(path, 0); if (item == null) { System.out.printf("%s: does not exist.\n", path); } else { // Keep track of the size of that JShellItem. int size = item.getSize(); if (size > 0) { List<String> recursiveList = recurseOnPath(path, true); rm(recursiveList.subList(0, size + 1)); if (item.getSize() == 0) { rm(recursiveList.subList(size + 1, size + 2)); } } else { if (item.getPath().equals("/")) { return; } // Check the -f option. if (!currentOptions_.equals("f")) { System.out.printf( "Really remove %s from %s? (y/n) ", item.getName(), item.getParentDirectory().getPath()); // Read the user input. ArrayList<String> in = readInput(); // If 'y' if (in.toString().equals("[y]")) { item.getParentDirectory().removeItem(item); // if not 'n', ask again. } else if (!in.toString().equals("[n]")) { List<String> tempStore = new ArrayList<String>(); tempStore.add(path); rm(tempStore); } // If -f is specified. } else { item.getParentDirectory().removeItem(item); } } } } }
/** * Gets the JShellItem located numFoldersUp numbers of folders up from the item located at path; * path can be a full path or a path relative to the current directory; if there is no such item, * returns null. * * <p>Call JShellItem(path, 0) to get the item located at path. * * @param path is a string that represents the full path to the JShellItem. * @param numFoldersUp * @return the JShellItem found at path or null if the item doesn't exist. */ public JShellItem getItemAtPath(String path, int numFoldersUp) throws Exception { JShellItem item = currentDirectory_; int startIndex = 0; if (path.startsWith("/")) { startIndex = 1; item = rootDirectory_; } String[] directories = path.split("/"); while (startIndex < directories.length - numFoldersUp) { if (directories[startIndex].equals("..")) { item = item.getParentDirectory(); startIndex++; } else if (((Directory) item).contains(directories[startIndex])) { if (item instanceof File) { throw new ClassCastException(item.getPath() + "is not a Directory"); } item = ((Directory) item).getItem(directories[startIndex]); startIndex++; } else if (!directories[startIndex].equals(".")) { return null; } else { startIndex++; } } return item; }
// TODO: Make ln fit the 30 line public void ln(String firstPath, String secondPath) throws Exception { // Initialize the variables. JShellItem targetItem; JShellItem aliasItem; String newName; Directory destinationDirectory; // Find and reference the target item. Throw Exception if the path // doesn't exist. targetItem = getItemAtPath(firstPath, 0); if (targetItem == null) { throw new Exception(firstPath + ": doesn't exist."); } // Find and reference the destination Directory. if (secondPath.endsWith("/")) { destinationDirectory = (Directory) getItemAtPath(secondPath, 0); newName = targetItem.getName(); } else { destinationDirectory = (Directory) getItemAtPath(secondPath, 1); newName = secondPath.substring(secondPath.lastIndexOf("/") + 1); } // If the Directory destination is not found. if (destinationDirectory == null) { throw new Exception(secondPath + " is an invalid destination path."); } // Throw Exception when there is a JShellItem that already exist within // the destination Directory. if (destinationDirectory.contains(newName)) { throw new Exception(secondPath + ": already exists."); } // If the target item is a Directory object. if (targetItem instanceof Directory) // Create a new Directory object that will references it's contents // from the target item. aliasItem = new DirectoryAlias( newName, destinationDirectory.getPath() + newName + "/", destinationDirectory, (Directory) targetItem); // If the target item is a File object. else // Create a new FileAlias object that will reference it's contents // from the target item. aliasItem = new FileAlias( newName, destinationDirectory.getPath() + newName, destinationDirectory, (File) targetItem); // Add the alias object to the destination Directory. destinationDirectory.addItem(aliasItem); }
/** * Display the content of File in the shell. * * @param file the full path or the name of a File in current directory. * @return the contents of the specified File object. */ public String cat(String file) throws Exception { // The file name given by the parameter is used to grab the file. JShellItem targetFile = getItemAtPath(file, 0); // If the file exists, then it returns the getContent method which // contains all of the files contents. if (targetFile != null) { return targetFile.getContent(); } else { return "The file was not found."; } }
/** * Return the names of the contained items, if path leads to a Directory. Or, return the path * provided, if it leads to a File. * * @param paths a list of Strings containing the desired paths. * @return a String containing the relevant contents. */ public String ls(List<String> paths) throws Exception { // If ls is called without parameters. if (paths.isEmpty()) { if (!currentOptions_.equals("R")) { if (currentDirectory_.getSize() == 0) { return ""; } else { return currentDirectory_.ls().substring(2); } } paths.add(currentDirectory_.getPath()); return ls(paths); // If ls is called with paramters. } else { String lsOutput = ""; for (int i = 0; i < paths.size(); i++) { JShellItem target = getItemAtPath(paths.get(i), 0); if (!lsOutput.isEmpty()) { lsOutput += "\n"; } lsOutput += paths.get(i); if (target == null) { lsOutput += ": No such file or directory"; } else { if (target instanceof Directory && currentOptions_.equals("R") && ((Directory) target).getNumDirectories() > 0 && !(target instanceof DirectoryAlias)) { List<String> recursivePath = recurseOnPath(paths.get(i), false); Collections.reverse(recursivePath); lsOutput += target.ls(); lsOutput += "\n"; lsOutput += ls(recursivePath.subList(1, recursivePath.size())); } else { // list paths separately lsOutput += target.ls(); // if there are more paths, print a blank line if (i < paths.size() - 1) { lsOutput += "\n"; } // notify user if there is an error in the path // specified } } } return lsOutput; } }
/** * If there's an operator and filename in the list of parameters, then if operator is '>', * overwrites the contents of outFile with the string text; if the operator is '>>', appends text * to the contents of outFile; If outFile doesn't exist, creates a new file outFile and appends * text to its contents. * * @param params A list of parameters which must include a string and may optionally include an * operator and a filename. */ public String echo(List<String> params) throws Exception { // The content to be output in retrieved String content = getContent(params); // The last index of the string, if it exists, in the List params. int last_index = getLastIndex(params); // If content is a valid string and the correct syntax is used to write // to a file, then this code is executed. if (params.size() > last_index + 2 && content.startsWith("\"") && content.endsWith("\"") && content.startsWith("\"") && params.get(last_index + 1).startsWith(">")) { // The file name and parameter for writing is retrieved. String file_name = params.get(last_index + 2); String param = params.get(last_index + 1); // The quotations are striped from the string to be used. content = content.substring(1, content.length() - 1); // The file is retrieved if it exists. JShellItem targetFile = getItemAtPath(file_name, 0); // The file is deleted if it exists and is to be overwritten. // Otherwise the file is created. if (!(param.equals(">>") & targetFile != null)) { if (targetFile != null) { targetFile.getParentDirectory().removeItem(targetFile); } mkfile(file_name); targetFile = getItemAtPath(file_name, 0); } // The file's contents are appended to either a blank (new) file // or an old file, depending on the user's input. ((File) targetFile).setContent(((File) targetFile).getContent() + content); return ""; // If the string is valid but the syntax is incorrect, then this // code is // executed. } else if (content.endsWith("\"") & content.startsWith("\"")) { if (content.substring(1, content.length() - 1).isEmpty()) { return content.substring(1, content.length() - 1); } return content.substring(1, content.length() - 1) + "\n"; // If the string is not valid, this code is executed. } else { return "Echo requires a string with \" & \" surrounding the words" + "\n"; } }
/** * @param path * @param includeFiles * @return * @throws Exception */ public List<String> recurseOnPath(String path, boolean includeFiles) throws Exception { List<String> paths = new ArrayList<String>(); JShellItem item = getItemAtPath(path, 0); if (!(item instanceof DirectoryAlias) && (includeFiles || item instanceof Directory)) { paths.add(item.getPath()); } if (item instanceof File) { return paths; } else { for (JShellItem cont : ((Directory) item).getContents().values()) { paths.addAll(0, recurseOnPath(cont.getPath(), includeFiles)); } } return paths; }
/** * Copy file or directory oldFile to newFile; * * @param oldFile a full path to a JShellItem or the name of a JShellItem in the current directory * which needs to be copied. * @param newFile a full path to a directory or the name of a directory in the current directory * to which oldFile needs to be copied. */ public void cp(String oldPath, String newPath) throws Exception { Directory destinationParent; String newName; if (oldPath.equals(newPath)) { return; } JShellItem oldItem = getItemAtPath(oldPath, 0); if (oldItem == null) { throw new Exception(oldItem + " does not exist."); } if (newPath.endsWith("/")) { destinationParent = (Directory) getItemAtPath(newPath, 0); newName = oldItem.getName(); } else { destinationParent = (Directory) getItemAtPath(newPath, 1); newName = newPath.substring(newPath.lastIndexOf("/") + 1); } if (destinationParent == null) { throw new Exception(newPath + " is an invalid destination path."); } if (destinationParent.contains(newName)) { throw new Exception(destinationParent.getPath() + newName + " already exists."); } if (oldItem instanceof File) { File newItem = new File( newName, destinationParent.getPath() + "/" + newName, destinationParent, ((File) oldItem).getContent()); destinationParent.addItem(newItem); } else { if (destinationParent.isChildOf((Directory) oldItem)) { throw new Exception( String.format("cp: cannot copy '%s' into itself, '%s'", oldPath, newPath)); } Directory newItem = new Directory(newName, destinationParent.getPath() + newName + "/", destinationParent); destinationParent.addItem(newItem); for (JShellItem item : ((Directory) oldItem).getContents().values()) { cp(item.getPath(), newItem.getPath()); } } }
/** * Prints the path of the files specified by the paths argument that contain a string that matches * regex, followed by the particular line. * * @param regex is a String regular expression. * @param paths is a List of paths. */ public String grep(String regex, List<String> paths) throws Exception { if (regex.startsWith("\"")) { int i = 0; for (i = 0; i < paths.size() && !regex.endsWith("\""); i++) regex += " " + paths.get(i); regex = regex.substring(1, regex.length() - 1); paths = paths.subList(i, paths.size()); } if (paths.isEmpty()) throw new Exception("Usage: grep [OPTION]... PATTERN [FILE]..."); String results = ""; for (String path : paths) { JShellItem item = getItemAtPath(path, 0); if (item.getSize() > 0 && currentOptions_.equals("R")) { results += grep(regex, recurseOnPath(path, true).subList(0, item.getSize())); } else if (item instanceof File) { String content = ((File) item).getContent(); if (content.contains(regex)) { if (!results.isEmpty()) results += "\n"; results += item.getPath() + ":\n"; for (String line : content.split("\\n")) { if (line.contains(regex)) { results += line + "\n"; } } results = results.substring(0, results.length() - 1); } } else if (item instanceof Directory && !currentOptions_.equals("R")) { results += "Cannot call grep on a directory without -R."; } else { results += ""; } } return results; }
/** * Move file or directory oldFile to newFile; * * @param oldFile a full path to a JShellItem or the name of a JShellItem in the current directory * which needs to be moved. * @param newFile a full path to a directory or the name of a directory in the current directory * to which oldFile needs to be moved. */ public void mv(String oldFile, String newFile) throws Exception { JShellItem source = getItemAtPath(oldFile, 0); if (source == null) { throw new Exception(oldFile + ": doesn't exist."); } Directory sourceParent = source.getParentDirectory(); Directory destinationParent; String newName; if (newFile.endsWith("/")) { destinationParent = (Directory) getItemAtPath(newFile, 0); newName = source.getName(); } else { destinationParent = (Directory) getItemAtPath(newFile, 1); newName = newFile.substring(newFile.lastIndexOf("/") + 1); } if (destinationParent == null) { throw new Exception(newFile + ": invalid destination path."); } if (destinationParent.contains(newName)) { throw new Exception(newFile + ": already exists."); } sourceParent.removeItem(source); source.setName(newName); if (source instanceof Directory) { if (destinationParent.isChildOf((Directory) source)) { throw new Exception( String.format( "mv: cannot move '%s' to a subdirectory of itself, '%s'", oldFile, newFile)); } newName.concat("/"); } source.setPath(destinationParent.getPath() + newName); source.setParentDirectory(destinationParent); destinationParent.addItem(source); }