Skip to content
Open
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
161055c
add: optparseを定義、lオプションを読み込めるようにした
1mori Jun 13, 2024
aac37f6
change: params -> options
1mori Jun 17, 2024
e2dc4f7
add: lオプションが指定された時の分岐となるif文をひとまず作成
1mori Jun 17, 2024
ff05df0
change: 9~12行目をメソッドの下に移動
1mori Jun 17, 2024
dfa3957
define: FILE_TYPE, FILE_MODEを定義
1mori Jun 17, 2024
867e38a
define: require 'etc'
1mori Jun 17, 2024
38942f2
add: 8進数のファイルモードを格納する変数file_mode_actalを定義
1mori Jun 17, 2024
5ae357c
add: nlink, uid, gid, size, mtimeを取得
1mori Jun 17, 2024
e3af6bf
add: 表示するファイルモードの文字列を作成するメソッドconvert_file_modeを作成
1mori Jun 17, 2024
4bde959
add: ファイルの総サイズの表示部分totalの作成
1mori Jun 17, 2024
08fcb9a
add: ファイルの特殊権限を確認するメソッドapply_special_modeを追加
1mori Jun 17, 2024
fdfadec
add: 予め表示するファイルモードをhashに格納するためにメソッドformat_file_modeを定義
1mori Jun 17, 2024
241960a
fix: format_file_modeで格納する文字列の細かな型の変更
1mori Jun 17, 2024
6757baf
define: ファイル情報の最大の文字数を取得するメソッドcalculate_max_string_modesを定義
1mori Jun 17, 2024
8cc5450
change: format_file_modeで求めたファイル情報を使用して文字の出力を実行
1mori Jun 17, 2024
f6df87e
fix: 同一名のhashを省略記法に変更
1mori Jun 17, 2024
44cdd4b
change: 空白埋めの調整
1mori Jun 17, 2024
69c4b53
fix: ファイルを示す文字が間違っていたので修正
1mori Jun 18, 2024
4d3313c
fix: スティッキービートなどの権限の確認後、文字列に反映させる処理がうまくいっていなかったので修正
1mori Jun 18, 2024
1b9593f
add: apply_special_modesに関する説明を追加
1mori Jun 19, 2024
1ba92aa
change: 0であるかどうか確認するif文をapply_special_modes内に移動
1mori Jun 19, 2024
d4d5ce3
fix: 特殊権限の付与ロジックが間違っていたので修正
1mori Jun 20, 2024
74c2e8c
change: 特殊権限の判定をビット演算に変更
1mori Jun 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 114 additions & 12 deletions 04.ls/ls.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,38 @@
#!/usr/bin/env ruby
# frozen_string_literal: true

require 'optparse'
require 'etc'

MAX_CHUNK = 3
TAB_SPACE = 8

file_paths = Dir.entries('.')
FILE_TYPE = {
'fifo' => 'p',
'characterSpecial' => 'c',
'directory' => 'd',
'blockSpecial' => 'b',
'file' => '-',
'link' => 'l',
'socket' => 's'
}.freeze

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] == '.' }
Expand All @@ -21,20 +49,94 @@ def transpose_chunks(sliced_paths, num_rows)
padded_slices.transpose.map(&:compact)
end

file_paths = file_paths.sort
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, 'l')

file_paths = except_hidden_file(file_paths)

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