Linux 文件操作

By | 2021年12月31日

1. echo 快速创建文件并追加

# 创建文件,并写入一行 aaa
echo "aaa" > text.txt
# 文件内容被 bbb 覆盖
echo "bbb" > text.txt
# 追加一行 ccc,bbb依然保留
echo "ccc" >> text.txt

> 创建并写入
>> 追加写入

2 cat命令

2.1 使用 cat > file << EOF 创建文件

cat>file<<EOF 这种用法用于创建文件,在这之后输入任何东西都是在文件里的,输入完成之后EOF(全称”end of file”)结尾代表结束,例如:

#!/bin/bash

# /home/admin/dev/aa/config 目录必须事先创建
cat > /home/admin/dev/aa/config/server.properties <<-EOF
broker.id=0
zookeeper.connect=127.0.0.1:2181
replica.socket.timeout.ms=1500
log.dirs=/kafka/logs
auto.create.topics.enable=true
offsets.topic.replication.factor=1
listeners=PLAINTEXT://0.0.0.0:9092,PLAINTEXT_HOST://0.0.0.0:19092
listener.security.protocol.map=PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
EOF

2.2 << 和 <<-区别

两个都是获取stdin,并在EOF处结束stdin,输出stdout。
如果重定向的操作符是<<-,那么分界符(EOF)所在行的开头部分的制表符(Tab)都将被去除。
在我们使用cat <<EOF时,我们输入完成后,需要在一个新的一行输入EOF结束stdin的输入。EOF必须顶行写,前面不能用制表符或者空格。比如,下面的语句就不会出错:

cat <<EOF  
Hello,world!  
EOF

如果结束分解符EOF前有制表符或者空格,则EOF不会被当做结束分界符,只会继续被当做stdin来输入。
而<<-就是为了解决这一问题:

cat <<-EOF  
Hello,world!  
      EOF

上面的写法,虽然最后的EOF前面有多个制表符和空格,但仍然会被当做结束分界符,表示stdin的结束。
这就是<<和<<-的区别。

2.3 使用 cat <<-END 将多行文本存变量

DEVICE_NAME="h3c"
USAGE=$(cat <<-END
if [deviceName] not in [ "${DEVICE_NAME}" ] {
    drop { }
}
END
)
echo $USAGE

3 envsubst 变量替换,常用于模板

# 安装 envsubst 工具
yum install -y gettext

将 tpt 文件中的变量 ${FEEDATA_HOME}、${FEESTORM_HOST} 全部替换成值,然后输出到 run/feezookeeper.yaml

export FEEDATA_HOME
export FEESTORM_HOST
envsubst '${FEEDATA_HOME} ${FEESTORM_HOST}'  < template/feezookeeper.yaml.tpt > run/feezookeeper.yaml

feezookeeper.yaml.tpt:

kind: Service
apiVersion: v1
metadata:
  name: feezookeeper
  labels:
    app: zookeeper-service
spec:
  clusterIP: None
  selector:
    app: zookeeper-pod
---

kind: StatefulSet
apiVersion: apps/v1
metadata:
  name: feezookeeper
spec:
  serviceName: feezookeeper
  replicas: 1
  selector:
    matchLabels:
      app: zookeeper-pod
  template:
    metadata:
      labels:
        app: zookeeper-pod
        selector: zookeeper-pod
    spec:
      containers:
        - name: zookeeper-pod
          image: localhost/zookeeper-feesec:local
          imagePullPolicy: Never
          env:
            - name: ZOO_LOG4J_PROP
              value: "INFO,ROLLINGFILE"
          volumeMounts:
            - name: zookeeper-data-volume
              mountPath: /data
      nodeSelector:
        kubernetes.io/hostname: ${FEESTORM_HOST}
      volumes:
        - name: zookeeper-data-volume
          hostPath:
            # Need to be created already and chmod 777
            path: ${FEEDATA_HOME}/zookeeper/data
            type: Directory

---

4 sed

4.1 打印文件指定行

# 打印文件第1行
sed -n '1p' readme.txt
# 打印文件第1到2行
sed -n '1,2p' readme.txt

4.2 多行匹配替换

文本内容:

fee-start
xxx
xxx
fee-end

匹配 start 和 end 之间的每一行,然后将 xxx 替换为 yyy:

sed -i '/fee-start/{:a;n;s/xxx/yyy/g;/fee-end/!ba}' <yourfile>

此 sed 命令,首先匹配 fee-start,匹配到后执行大括号里的语句。
n 读取下一行。
s/xxx/yyy/g 将 xxx 替换为 yyy,全局替换,同一行中出现几次替换几次。
:a 设定跳转标签 a。
/fee-end/!ba 当前行匹配不上 fee-end,则跳转到标签a处继续执行,构成一个循环。若匹配到,则退出循环,sed重新对读入的每行匹配 fee-start。

5 find

# 在根目录下查找blog-compose.yml文件
find / -name blog-compose.yml

# 在根目录下查找文件名含有compose的文件
find / -name "*compose*"

6 linux shell 指令 

-e 判断对象是否存在
-d 判断对象是否存在,并且为目录
-f 判断对象是否存在,并且为常规文件
-L 判断对象是否存在,并且为符号链接
-h 判断对象是否存在,并且为软链接
-s 判断对象是否存在,并且长度不为0
-r 判断对象是否存在,并且可读
-w 判断对象是否存在,并且可写
-x 判断对象是否存在,并且可执行
-O 判断对象是否存在,并且属于当前用户
-G 判断对象是否存在,并且属于当前用户组
-nt 判断file1是否比file2新 [ “/data/file1” -nt “/data/file2” ]
-ot 判断file1是否比file2旧 [ “/data/file1” -ot “/data/file2” ]

注意:权限不够也会被认为不存在。

例如:

#!/bin/bash

if [ -f "/home/admin/dev/docker/test-falpolicy-compose.yml" ];then
    echo "文件存在"
else
    echo "文件不存在"
fi

7 读文件夹里文件,并按数组格式输出

#!/bin/sh

if [ $# != 1 ]; then
echo "input error."
exit 1
fi

file_subffix=$1

output=""

filelist="ls *.${file_subffix}"
for file in $filelist
do
    #echo ${file}
    if [ ${file} == "ls" ];then
        continue
    fi
    output=${output}\"${file}\",
done

echo "file_list:"
echo "[${output%?}]"

将脚本放在要读文件的目录下,返回的 jpg 文件结果:

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注