Here, we will see Simulation of Linux cd command in Go. We will do directory changes without OS call with program.
Simulating a “cd” Linux command that changes a current directory in a file system. The simulated command takes two path strings from the command line and prints either a new path or an error.
The first path is a current working directory and second path is a new directory. Here a directory name can only contain alphanumeric characters.
- A single dot (“.”) indicates a current directory.
- the two dots (“..”) indicate a step to a previous directory, up from the current one.
- A single forward slash “/” indicates a root directory.
- Multiple consecutive slashes (////) are treated as equivalent to one (/).
You have to print a new path.
Example:
$ go build mycd.go $ ./mycd / abc Output: /abc $ mycd /abc/def ghi Output: /abc/def/ghi $ mycd /abc/def .. Output: /abc $ mycd /abc/def /abc Output: /abc $ mycd /abc/def /abc/klm Output: /abc/klm $ mycd /abc/def ../.. Output: / $ mycd /abc/def ../../.. Output: / $ mycd /abc/def . Output: /abc/def $ mycd /abc/def ..klm Output: ..klm: No such file or directory $ mycd /abc/def ////// Output: / $ mycd /abc/def ...... Output: ......: No such file or directory $ mycd /abc/def ../gh///../klm/. Output: /abc/klm
Code to Simulation of Linux cd command in Go
package main import ( "fmt" "os" "regexp" "strings" ) func remove_index_from_slice_of_strings(slice []string, index int) []string { return append(slice[:index], slice[index+1:]...) } func panic_recovery(err error) { if err := recover(); err != nil { //catch fmt.Println("mycd: ", err) os.Exit(1) } } func is_alphanum(word string) bool { return regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(word) } func remove_empty_index_in_slice(slice []string, from_index int) []string { for i := from_index; i < len(slice); { if strings.Compare(slice[i], "") == 0 { slice = remove_index_from_slice_of_strings(slice, i) } else { break } } return slice } func validate_and_convert_dir_path_to_slice(dir_path string) []string { dir_path_list := strings.Split(dir_path, "/") if strings.Compare(dir_path_list[0], "") == 0 { dir_path_list = remove_empty_index_in_slice(dir_path_list, 1) } for i, dir_name := range dir_path_list { // Validate if dir name is alphanumeric or not if !(is_alphanum(dir_name) || (strings.Compare(dir_name, "..") == 0) || (strings.Compare(dir_name, ".") == 0)) { panic(dir_name + ": No such file or directory") } // Remove extra backslashes if persists (In strings.Split with "/" // converts backslashes to empty string) if strings.Compare(dir_name, "") == 0 { if i == 0 { // ignore first backslash if exists continue } dir_path_list = remove_empty_index_in_slice(dir_path_list, i) } } return dir_path_list } func back_to_the_child_path(cwd []string) []string { return append(cwd[:len(cwd)-1], cwd[len(cwd):]...) } func prepare_new_dir(cwd_dir_path_list, new_dir_path_list []string) string { new_dir := "/" if strings.Compare(new_dir_path_list[0], "") == 0 { // If target path starts with "/". Checking with empty string because In strings.Split with "/" // "/" converts backslash to empty string in slice of strings if len(new_dir_path_list) == 1 && strings.Compare(new_dir_path_list[0], "") == 0 { // If target has only backslash "/" return new_dir } new_dir = strings.Join(new_dir_path_list, "/") return new_dir } for i := 0; i < len(new_dir_path_list); i++ { if strings.Compare(new_dir_path_list[i], "") == 0 || strings.Compare(new_dir_path_list[i], ".") == 0 { continue } if strings.Compare(new_dir_path_list[i], "..") == 0 { if len(cwd_dir_path_list) > 1 { cwd_dir_path_list = back_to_the_child_path(cwd_dir_path_list) } } else { cwd_dir_path_list = append(cwd_dir_path_list, new_dir_path_list[i]) } } if len(cwd_dir_path_list) == 1 && strings.Compare(cwd_dir_path_list[0], "") == 0 { return new_dir } else { new_dir = strings.Join(cwd_dir_path_list, "/") return new_dir } } func main() { defer panic_recovery(nil) if len(os.Args) < 3 { panic("too few arguments") } else if len(os.Args) > 3 { panic("too many arguments") } cwd := os.Args[1] to_dirctory := os.Args[2] cwd_dir_path_list := validate_and_convert_dir_path_to_slice(cwd) new_dir_path_list := validate_and_convert_dir_path_to_slice(to_dirctory) new_dir := prepare_new_dir(cwd_dir_path_list, new_dir_path_list) fmt.Println(new_dir) }
Output:
% go build mycd.go % ./mycd /abc wd/ss/../dsds/../dd/ddee/./../ Output: /abc/wd/dd
To check more leetcode problem’s solution. Pls click given below link:
https://www.techieindoor.com/category/leetcode/