後綴亂了就三檔一起跑
月末清理下載資料夾和照片備份目錄,最亂的是後綴:JPG、jpg、Jpg 同層混著。我把檔名整段貼進後綴大小寫頁,三種檔位各跑一遍——樣本是自己列的一張清單:貼進去 20 段、有效 18 行,名字全是虛構的。
頁面本體實測 211 行、8526 位元組,convertExt 在第 88–113 行,三檔共用同一句按下標拼串。這篇引的數全部出自 後綴大小寫轉換 這一頁的純函式返回值口徑。
有些後綴轉換完整行會變長
clip.ß 的後綴是 ß,1 枚碼元;upper 檔還回 SS 兩枚,整串從 6 碼元漲到 7 碼元,可 UTF-8 位元組數兩邊都是 7。
dot.İ 只有 lower 檔會動:İ 被換成 i 加組合點,後綴 1 碼元變 2,整串碼元 5 到 6、位元組 6 到 7;upper 檔把它摺回原字元,整行不動,記「未變化」。
mix.İß 是三檔分歧的那一行:後綴 2 碼元、整串 6 碼元 8 位元組——upper 給 7 碼元仍 8 位元組,lower 給 7 碼元還 9 位元組,title 一動不動。
落到我那 18 行有效清單上:upper 檔變長 2 行、lower 檔變長 2 行、title 檔變長 1 行。
帶點的名字不一定有後綴
名字長這樣——a.、photo.、..、...、D:\dir.、.bashrc.、archive.tar.,最後一個點全卡在末尾,位置分別是 dot=1、5、1、2、6、7、11。第 92 行只擋 dot<=0,這些全被放行;第 97 行 substring(dot+1) 切出來是長度 0 的空串;第 138 行的 !r.ext 於是把它們和整行沒點的名字歸進同一格——「無後綴」與「未變化」兩個計數器同時加一。7 條各跑 3 檔共 21 次呼叫,返回值與入參逐字元相同。「從最後一個點起算」的判法我單獨寫過一篇,不在這裡復述。
| 名字 | dot | 切出的後綴 | 三檔結果 |
|---|---|---|---|
photo. | 5 | 空串 | 三檔全同入參 |
D:\dir. | 6 | 空串 | 三檔全同入參 |
.bashrc. | 7 | 空串 | 三檔全同入參 |
archive.tar. | 11 | 空串 | 三檔全同入參 |
archive.tar.gz | 10 | gz | gz 照常換檔 |
行首縮排會被悄悄吃掉
首尾空白在兩處各被剪了一次:process 的第 134 行一次,convertExt 的第 89 行又來一次同一條正則。所以帶 4 個行首空格和 1 個行尾製表符的一行,原始 22 碼元,進入返回值裡 before 已經是 17 碼元。
只餵 convertExt 一處時,13 碼元的 " photo.JPG " 出來 before 是 9 碼元;詞中間的空格剪不掉:20 碼元的 " spaced name .TXT " 剪完 16 碼元,點前面那個空格照舊留著。轉換前列、轉換後列、複製文字這三處,在函式返回值層是同一個剪好的串。
貼進去多少行不等於處理了多少個
清單貼進去 20 段,split(/\r?\n/) 得 20 段,進表只有 18 行:1 個純空格段和 1 個空段在第 135 行被直接跳過。三檔四數:
| 檔位 | 總檔案數 | 已轉換 | 未變化 | 無後綴 |
|---|---|---|---|---|
| upper | 18 | 7 | 11 | 4 |
| lower | 18 | 8 | 10 | 4 |
| title | 18 | 8 | 10 | 4 |
已轉換加未變化等於總檔案數,在這張清單三檔都成立:7+11=18、8+10=18。那句「已處理 18 個檔名」報的就是 total,不是貼上段數 20。
表裡的序號也不是貼上位置:把 first.JPG、空行、second.TAR.gz、純空格行、third.7z、尾隨換行這 6 段餵進去,split 得 6 段、總檔案數 3、有效原始行號 1,3,5,表格 # 列(第 158 行的 idx+1)連著排成 1,2,3。檔位切換只在結果已經顯示出來時才自動重跑(第 82–84 行),且第 131 行每次先清空舊結果,三檔四數是三套獨立計數而不是累加。
示例按鈕灌的 7 行(第 190–198 行)是組現成對照。同一段文字,upper 只轉 1 行、lower 轉 5 行、title 轉 6 行,已轉換占比從 14.3% 一路漲到 85.7%。
表格裡看到的和複製出來的不是同一份文字
表格儲存格要過一道 escHtml(第 116–118 行):先 &、再 <、再 >、最後引號,四步連做。於是 all <>&".LOG 這個 12 碼元的 after,在表格裡是 27 碼元的實體串;a<b>.TXT 從 8 碼元變 14;quote".TXT 從 10 碼元變 15。
複製走的是另一條路(第 185 行):只取每行的 after 這一個欄位,用單個換行相連——不帶序號列、不帶轉換前列、不經 escHtml。上面那個 12 碼元的名字,複製出去還是 12 碼元原串。
圖 1:變長是碼元層的賬,位元組是另一本,兩本不同步
這一頁只產出文字,真要改名字是另一頁 批次重新命名 的事,這篇不替它寫一個字。
文案裡沒提空行,也沒提變長
把工具條目的文案逐條對了一遍,共 14 條判定:一致 6、部分一致 7、衝突 1。五行文案裡沒有「空行」二字,可 20 段貼上對 total 18 的差,正是跳過空行行為給的賬。名字長度沒有上限:200 個 x 加 .JPG 共 204 碼元照樣整串吐回。空文字框、純換行、4 個空格、剪出 5 段全是空行與空格的那一串,都被第 126 行的守衛攔下,只彈「請輸入檔名」;第 153 行那句「無有效資料」在函式層拿不到輸入,清空結果後再點複製,只彈「暫無結果可複製」。
FAQ
Q:檔名一個字沒變,為什麼有的記「已轉換」有的記「未變化」?
判據只看返回串與入參是否逐字元全等。word.ς 的 upper 給 word.Σ,長度沒變、碼位變了,就是已轉換;dot.İ 的 upper、roman.Ⅷ 的 upper 摺疊回原字元,整行不動,記未變化。
Q:多出來的那一個字元是哪來的?
是大小寫映射自己的返回值:ß 大寫還給 SS、İ 小寫還給 i 加一枚組合點,1 碼元進 2 碼元出。這一頁按下標拼串、對返回值不做長度兜底,所以 clip.ß 的 upper 整串從 6 碼元漲到 7,而 UTF-8 位元組數停在 7。
Q:點在最末尾為什麼算無後綴?
dot 大於 0 時 substring 從 dot+1 起切,切出空串,!r.ext 把它們歸到「無後綴」與「未變化」同一格。同為 11 個字元長的名字,archive.tar. 報無後綴,archive.tar.gz 照常轉 gz——差別只在最後一個點後面還有沒有字元。
Q:表格裡的那一行和複製出來的是同一串嗎?
名字不含 &、<、>、引號時是同一串;含就有差——all <>&".LOG 在表格裡是 27 碼元實體,複製出去是 12 碼元原文。螢幕實際渲染未實測,對賬以複製文字為準。