From ec150d3acdf0d73449a6dcfbd981ef5bc32b90e0 Mon Sep 17 00:00:00 2001 From: "yuichi.imori" Date: Mon, 3 Jun 2024 10:59:33 +0900 Subject: [PATCH 01/10] =?UTF-8?q?-a=E3=82=AA=E3=83=97=E3=82=B7=E3=83=A7?= =?UTF-8?q?=E3=83=B3=E3=82=92=E5=8F=97=E3=81=91=E4=BB=98=E3=81=91=E3=82=8B?= =?UTF-8?q?ls=E3=82=B3=E3=83=9E=E3=83=B3=E3=83=89=E3=83=97=E3=83=AD?= =?UTF-8?q?=E3=82=B0=E3=83=A9=E3=83=A0=E3=82=92=E4=BD=9C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 04.ls/ls.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/04.ls/ls.rb b/04.ls/ls.rb index 6b1cfd48e4..ceb916cd96 100755 --- a/04.ls/ls.rb +++ b/04.ls/ls.rb @@ -1,11 +1,17 @@ #!/usr/bin/env ruby # frozen_string_literal: true +require 'optparse' + MAX_CHUNK = 3 TAB_SPACE = 8 file_paths = Dir.entries('.') +opt = OptionParser.new +params = opt.getopts(ARGV, 'a') +p params['a'] + def except_hidden_file(file_paths) file_paths.reject { |element| element[0] == '.' } end @@ -22,7 +28,8 @@ def transpose_chunks(sliced_paths, num_rows) end file_paths = file_paths.sort -file_paths = except_hidden_file(file_paths) +file_paths = except_hidden_file(file_paths) if params['a'] == false + num_rows = (file_paths.size.to_f / MAX_CHUNK).ceil sliced_paths = chunk_file_paths(file_paths, num_rows) From 97b7998b909fc7c8e1bcaa8584ff7c381f25c135 Mon Sep 17 00:00:00 2001 From: "yuichi.imori" Date: Fri, 7 Jun 2024 12:37:21 +0900 Subject: [PATCH 02/10] =?UTF-8?q?delete:=20=E3=83=87=E3=83=90=E3=83=83?= =?UTF-8?q?=E3=82=AF=E6=96=87=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 04.ls/ls.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/04.ls/ls.rb b/04.ls/ls.rb index ceb916cd96..03ce27951d 100755 --- a/04.ls/ls.rb +++ b/04.ls/ls.rb @@ -10,7 +10,6 @@ opt = OptionParser.new params = opt.getopts(ARGV, 'a') -p params['a'] def except_hidden_file(file_paths) file_paths.reject { |element| element[0] == '.' } From 12e735be594d77cfe1f2e5ed8fd01d4b4b5ae2ed Mon Sep 17 00:00:00 2001 From: "yuichi.imori" Date: Fri, 7 Jun 2024 12:49:12 +0900 Subject: [PATCH 03/10] =?UTF-8?q?delete:=20=E5=BF=85=E8=A6=81=E4=BB=A5?= =?UTF-8?q?=E4=B8=8A=E3=81=AE=E6=94=B9=E8=A1=8C=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 04.ls/ls.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/04.ls/ls.rb b/04.ls/ls.rb index 03ce27951d..c22b2303a5 100755 --- a/04.ls/ls.rb +++ b/04.ls/ls.rb @@ -29,7 +29,6 @@ def transpose_chunks(sliced_paths, num_rows) file_paths = file_paths.sort file_paths = except_hidden_file(file_paths) if params['a'] == false - num_rows = (file_paths.size.to_f / MAX_CHUNK).ceil sliced_paths = chunk_file_paths(file_paths, num_rows) shaped_file_paths_array = transpose_chunks(sliced_paths, num_rows) From e35826977124fc5f8fe9907c838144924c5ad67b Mon Sep 17 00:00:00 2001 From: "yuichi.imori" Date: Mon, 10 Jun 2024 10:05:15 +0900 Subject: [PATCH 04/10] =?UTF-8?q?change:=20=E6=9D=A1=E4=BB=B6=E5=88=86?= =?UTF-8?q?=E5=B2=90=E8=A8=98=E6=B3=95=E3=81=AE=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 04.ls/ls.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/04.ls/ls.rb b/04.ls/ls.rb index c22b2303a5..9412733d44 100755 --- a/04.ls/ls.rb +++ b/04.ls/ls.rb @@ -27,7 +27,7 @@ def transpose_chunks(sliced_paths, num_rows) end file_paths = file_paths.sort -file_paths = except_hidden_file(file_paths) if params['a'] == false +file_paths = except_hidden_file(file_paths) unless params['a'] num_rows = (file_paths.size.to_f / MAX_CHUNK).ceil sliced_paths = chunk_file_paths(file_paths, num_rows) From 5940c0103d57014f5333255db49befff928648c6 Mon Sep 17 00:00:00 2001 From: "yuichi.imori" Date: Tue, 11 Jun 2024 10:09:19 +0900 Subject: [PATCH 05/10] =?UTF-8?q?add:=20r=E3=82=AA=E3=83=97=E3=82=B7?= =?UTF-8?q?=E3=83=A7=E3=83=B3=E3=81=AEcherry-pick?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 04.ls/ls.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/04.ls/ls.rb b/04.ls/ls.rb index 9412733d44..49cc03301d 100755 --- a/04.ls/ls.rb +++ b/04.ls/ls.rb @@ -11,6 +11,9 @@ opt = OptionParser.new params = opt.getopts(ARGV, 'a') +opt = OptionParser.new +params = opt.getopts(ARGV, 'r') + def except_hidden_file(file_paths) file_paths.reject { |element| element[0] == '.' } end @@ -26,7 +29,7 @@ def transpose_chunks(sliced_paths, num_rows) padded_slices.transpose.map(&:compact) end -file_paths = file_paths.sort +file_paths = params['r'] ? file_paths.sort.reverse : file_paths.sort file_paths = except_hidden_file(file_paths) unless params['a'] num_rows = (file_paths.size.to_f / MAX_CHUNK).ceil From 20438cf5d3388ad2dd35c44f6def69ee43397e73 Mon Sep 17 00:00:00 2001 From: "yuichi.imori" Date: Mon, 24 Jun 2024 12:01:13 +0900 Subject: [PATCH 06/10] =?UTF-8?q?delete:=20=E9=87=8D=E8=A4=87=E3=81=99?= =?UTF-8?q?=E3=82=8Bopt=E3=81=AE=E8=A8=98=E8=BF=B0=E3=82=92=E5=89=8A?= =?UTF-8?q?=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 04.ls/ls.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/04.ls/ls.rb b/04.ls/ls.rb index 49cc03301d..b4191c48de 100755 --- a/04.ls/ls.rb +++ b/04.ls/ls.rb @@ -10,8 +10,6 @@ opt = OptionParser.new params = opt.getopts(ARGV, 'a') - -opt = OptionParser.new params = opt.getopts(ARGV, 'r') def except_hidden_file(file_paths) From 9fa790f42ff637762f72d92dc39445d806840e7e Mon Sep 17 00:00:00 2001 From: "yuichi.imori" Date: Wed, 12 Jun 2024 10:04:13 +0900 Subject: [PATCH 07/10] chenge: params -> options --- 04.ls/ls.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/04.ls/ls.rb b/04.ls/ls.rb index b4191c48de..738c087511 100755 --- a/04.ls/ls.rb +++ b/04.ls/ls.rb @@ -9,8 +9,8 @@ file_paths = Dir.entries('.') opt = OptionParser.new -params = opt.getopts(ARGV, 'a') -params = opt.getopts(ARGV, 'r') +options = opt.getopts(ARGV, 'r') +options = opt.getopts(ARGV, 'a') def except_hidden_file(file_paths) file_paths.reject { |element| element[0] == '.' } @@ -27,8 +27,8 @@ def transpose_chunks(sliced_paths, num_rows) padded_slices.transpose.map(&:compact) end -file_paths = params['r'] ? file_paths.sort.reverse : file_paths.sort -file_paths = except_hidden_file(file_paths) unless params['a'] +file_paths = options['r'] ? file_paths.sort.reverse : file_paths.sort +file_paths = except_hidden_file(file_paths) unless options['a'] num_rows = (file_paths.size.to_f / MAX_CHUNK).ceil sliced_paths = chunk_file_paths(file_paths, num_rows) From ed87f42eaaf5e127b081799ac1878e13b0b34065 Mon Sep 17 00:00:00 2001 From: "yuichi.imori" Date: Wed, 12 Jun 2024 10:05:42 +0900 Subject: [PATCH 08/10] =?UTF-8?q?change:=20sort=E3=81=99=E3=82=8B=E7=AE=87?= =?UTF-8?q?=E6=89=80=E3=81=AE=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 04.ls/ls.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/04.ls/ls.rb b/04.ls/ls.rb index 738c087511..583cab65e6 100755 --- a/04.ls/ls.rb +++ b/04.ls/ls.rb @@ -6,7 +6,7 @@ MAX_CHUNK = 3 TAB_SPACE = 8 -file_paths = Dir.entries('.') +file_paths = Dir.entries('.').sort opt = OptionParser.new options = opt.getopts(ARGV, 'r') @@ -27,7 +27,7 @@ def transpose_chunks(sliced_paths, num_rows) padded_slices.transpose.map(&:compact) end -file_paths = options['r'] ? file_paths.sort.reverse : file_paths.sort +file_paths = file_paths.reverse if options['r'] file_paths = except_hidden_file(file_paths) unless options['a'] num_rows = (file_paths.size.to_f / MAX_CHUNK).ceil From b18fc9d5743d01b6e3e520a8fe468f3b74611135 Mon Sep 17 00:00:00 2001 From: "yuichi.imori" Date: Mon, 24 Jun 2024 12:22:14 +0900 Subject: [PATCH 09/10] =?UTF-8?q?add:=20l=E3=82=AA=E3=83=97=E3=82=B7?= =?UTF-8?q?=E3=83=A7=E3=83=B3=E3=81=AE=E5=A4=89=E6=9B=B4=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cherry-pickdで追加するには項目が多すぎたため --- 04.ls/ls.rb | 125 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 111 insertions(+), 14 deletions(-) diff --git a/04.ls/ls.rb b/04.ls/ls.rb index 583cab65e6..80f2727491 100755 --- a/04.ls/ls.rb +++ b/04.ls/ls.rb @@ -2,15 +2,37 @@ # frozen_string_literal: true require 'optparse' +require 'etc' MAX_CHUNK = 3 TAB_SPACE = 8 -file_paths = Dir.entries('.').sort +FILE_TYPE = { + 'fifo' => 'p', + 'characterSpecial' => 'c', + 'directory' => 'd', + 'blockSpecial' => 'b', + 'file' => '-', + 'link' => 'l', + 'socket' => 's' +}.freeze -opt = OptionParser.new -options = opt.getopts(ARGV, 'r') -options = opt.getopts(ARGV, 'a') +FILE_MODE = { + '0' => '---', + '1' => '--x', + '2' => '-w-', + '3' => '-wx', + '4' => 'r--', + '5' => 'r-x', + '6' => 'rw-', + '7' => 'rwx' +}.freeze + +SPECIAL_MODE = [ + { bit: 4, index: 2, exec: 's', no_exec: 'S' }, + { bit: 2, index: 5, exec: 's', no_exec: 'S' }, + { bit: 1, index: 8, exec: 't', no_exec: 'T' } +].freeze def except_hidden_file(file_paths) file_paths.reject { |element| element[0] == '.' } @@ -27,20 +49,95 @@ def transpose_chunks(sliced_paths, num_rows) padded_slices.transpose.map(&:compact) end +def convert_file_mode(file_stat) + file_mode_octal = file_stat.mode.to_s(8).rjust(6, '0') + file_mode = FILE_TYPE[file_stat.ftype].to_s + file_permissions = file_mode_octal.slice(3..-1).chars.map { |char| FILE_MODE[char] }.join + # 特殊権限の確認 特殊権限は8進数に変換されたファイルモードの3文字目に記載されている そのためfile_mode_octal[2]を参照する + file_permissions = apply_special_modes(file_mode_octal[2].to_i, file_permissions) + file_mode + file_permissions +end + +def apply_special_modes(special_modes, permissions) + # 0は特殊権限なし、なので最初に弾く(特殊権限は1か2か4であるため) + return permissions if special_modes.zero? + + SPECIAL_MODE.each do |mode| + next unless (special_modes & mode[:bit]).positive? + + permissions[mode[:index]] = if permissions[mode[:index]] == 'x' + mode[:exec] + else + mode[:no_exec] + end + end + permissions +end + +def format_file_mode(file_path) + file_stat = File.lstat(file_path) + { + file_mode: convert_file_mode(file_stat), + nlink: file_stat.nlink.to_s, + uid: Etc.getpwuid(file_stat.uid).name, + gid: Etc.getgrgid(file_stat.gid).name, + size: file_stat.size.to_s, + mtime: file_stat.mtime.strftime('%-m %d %H:%M'), + file_path:, + blocks: file_stat.blocks + } +end + +def calclate_max_string_modes(file_modes) + { + nlink: file_modes.map { |file_mode| file_mode[:nlink].size }.max, + uid: file_modes.map { |file_mode| file_mode[:uid].size }.max, + gid: file_modes.map { |file_mode| file_mode[:gid].size }.max, + size: file_modes.map { |file_mode| file_mode[:size].size }.max, + mtime: file_modes.map { |file_mode| file_mode[:mtime].size }.max + } +end + +file_paths = Dir.entries('.').sort + +opt = OptionParser.new +options = opt.getopts(ARGV, 'r', 'a', 'l') + file_paths = file_paths.reverse if options['r'] file_paths = except_hidden_file(file_paths) unless options['a'] -num_rows = (file_paths.size.to_f / MAX_CHUNK).ceil -sliced_paths = chunk_file_paths(file_paths, num_rows) -shaped_file_paths_array = transpose_chunks(sliced_paths, num_rows) +if options['l'] + file_modes = file_paths.map { |file_path| format_file_mode(file_path) } + total_blocks = file_modes.map { |file_mode| file_mode[:blocks] }.sum + + puts "total #{total_blocks}" + + max_string_modes = calclate_max_string_modes(file_modes) + file_modes.each do |file_mode| + file_mode_print = [ + file_mode[:file_mode], + file_mode[:nlink].rjust(max_string_modes[:nlink]), + file_mode[:uid].ljust(max_string_modes[:uid]), + file_mode[:gid].rjust(max_string_modes[:gid] + 1), + file_mode[:size].rjust(max_string_modes[:size] + 1), + file_mode[:mtime].rjust(max_string_modes[:mtime] + 1), + file_mode[:file_path] + ].join(' ') + puts file_mode_print + end +else + num_rows = (file_paths.size.to_f / MAX_CHUNK).ceil + sliced_paths = chunk_file_paths(file_paths, num_rows) + shaped_file_paths_array = transpose_chunks(sliced_paths, num_rows) -max_string_length = file_paths.map(&:length).max + max_string_length = file_paths.map(&:length).max -shaped_file_paths_array.each do |array_element| - array_element.each do |element| - tab_count = ((max_string_length - element.length) / TAB_SPACE.to_f).ceil + 1 # タブの挿入する回数を計算 - print element - print "\t" * tab_count + shaped_file_paths_array.each do |array_element| + array_element.each do |element| + tab_count = ((max_string_length - element.length) / TAB_SPACE.to_f).ceil + 1 # タブの挿入する回数を計算 + print element + print "\t" * tab_count + end + puts end - puts end From fd4341fca3c5d862a4e6a7861fb42a6db4dd361b Mon Sep 17 00:00:00 2001 From: "yuichi.imori" Date: Mon, 24 Jun 2024 12:35:42 +0900 Subject: [PATCH 10/10] =?UTF-8?q?change:=20=E8=A4=87=E6=95=B0=E3=82=AA?= =?UTF-8?q?=E3=83=97=E3=82=B7=E3=83=A7=E3=83=B3=E3=82=92=E6=8C=87=E5=AE=9A?= =?UTF-8?q?=E3=81=A7=E3=81=8D=E3=82=8B=E6=9B=B8=E3=81=8D=E6=96=B9=E3=81=AB?= =?UTF-8?q?=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 04.ls/ls.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/04.ls/ls.rb b/04.ls/ls.rb index 80f2727491..089cf6517e 100755 --- a/04.ls/ls.rb +++ b/04.ls/ls.rb @@ -101,7 +101,7 @@ def calclate_max_string_modes(file_modes) file_paths = Dir.entries('.').sort opt = OptionParser.new -options = opt.getopts(ARGV, 'r', 'a', 'l') +options = opt.getopts(ARGV, 'arl') file_paths = file_paths.reverse if options['r'] file_paths = except_hidden_file(file_paths) unless options['a']