我需要查找并洗掉空檔案。在我的用例中,空檔案的定義是一個零行的檔案。
我確實嘗試測驗檔案以查看它是否為空但是,這表現得很奇怪,因為即使檔案為空,它也沒有檢測到它。
因此,我能寫出的最好的東西是下面的腳本,我太慢了,因為它必須測驗幾十萬個檔案
#!/bin/bash
LOOKUP_DIR="/path/to/source/directory"
cd ${LOOKUP_DIR} || { echo "cd failed"; exit 0; }
for fname in $(realpath */*)
do
if [[ $(wc -l "${fname}" | awk '{print $1}') -eq 0 ]]
then
echo "${fname}" is empty
rm -f "${fname}"
fi
done
有沒有更好的方法來做我想做的事情,或者,上面的邏輯可以用一種帶來更好性能的方式重寫嗎?
uj5u.com熱心網友回復:
您的腳本很慢,因為wc將每個檔案都讀到最后,這不是您的目的所必需的。這可能是您要找的:
#!/bin/bash
lookup_dir='/path/to/source/directory'
cd "$lookup_dir" || exit
for file in *; do
if [[ -f "$file" && -r "$file" && ! -L "$file" ]]; then
read < "$file" || echo rm -f -- "$file"
fi
done
echo在確保它按預期作業后洗掉。
另一個版本,rm只呼叫一次,可能是:
#!/bin/bash
lookup_dir='/path/to/source/directory'
cd "$lookup_dir" || exit
for file in *; do
if [[ -f "$file" && -r "$file" && ! -L "$file" ]]; then
read < "$file" || files_to_be_deleted =("$file")
fi
done
rm -f -- "${files_to_be_deleted[@]}"
說明:
核心邏輯在行
read < "$file" || rm -f -- "$file"
該read < "$file" 命令嘗試從$file. 如果成功,即讀取了一行,則不會執行rm右側的命令||(這就是||作業原理)。如果失敗,rm則將執行該命令。在任何情況下,最多只能讀取一行。這比wc命令有很大的優勢,因為它wc會讀取整個檔案。
if ! read < "$file"; then rm -f -- "$file"; fi
可以代替。兩行是等價的。
uj5u.com熱心網友回復:
要檢查“$fname”是否為檔案并且是否為空,請使用[ -s "$fname" ]:
#!/usr/bin/env sh
LOOKUP_DIR="/path/to/source/directory"
for fname in "$LOOKUP_DIR"*/*; do
if ! [ -s "$fname" ]; then
echo "${fname}" is empty
# remove echo when output is what you want
echo rm -f "${fname}"
fi
done
見help test::
檔案運算子:
...
-s FILE 如果檔案存在且不為空,則為真。
uj5u.com熱心網友回復:
還有一種方法
wc -l ~/tmp/* 2>/dev/null | awk '$1 == 0 {print $2}' | xargs echo rm
如果您的任何檔案的名稱中有空格,這將中斷。
要解決這個問題,仍然使用 awk
wc -l ~/tmp/* 2>/dev/null \
| awk 'sub(/^[[:blank:]] 0[[:blank:]] /, "")' \
| xargs echo rm
這是有效的,因為該sub函式回傳所做的替換次數,可以將其視為布爾零/非零條件。
洗掉 echo 以實際洗掉檔案。
uj5u.com熱心網友回復:
使用 ruby?? one-liner查找空檔案(即沒有換行符):
ruby -rfind -e 'Find.find(*ARGV){|f| puts f if File.file?(path) && File.open(f,&:gets)[-1] != "\n" rescue nil}' /path/to/source/directory
程式將嘗試讀取在源目錄(及其后代)中找到的每個檔案的第一行,如果成功,則測驗該行的最后一個字符(應該是 a \n):當該行沒有以 a 終止,\n然后你就成功了。
注意:
當前代碼只輸出應該洗掉的檔案。如果正確,則替換puts f為File.delete(f)
太慢了,因為它必須測驗幾十萬個檔案
上面的提議應該是很快的(也就是對于單執行緒的方案)
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/387462.html
