When automating file deployments using find
commands, we often encounter path prefixes that interfere with our copy operations. Consider this common scenario:
find . -type f -mtime -14 > deploy.txt
# Output contains './path/to/file.ext'
# But we need just 'path/to/file.ext'
Here are three effective approaches to remove the leading ./
:
1. Using parameter expansion in a loop
find . -type f -mtime -14 | while read -r file; do
echo "${file#./}" >> deploy.txt
done
2. Leveraging sed for direct stream editing
find . -type f -mtime -14 | sed 's|^\./||' > deploy.txt
3. Using printf formatting with find -print0
find . -type f -mtime -14 -printf '%P\\n' > deploy.txt
Here's how I integrated this into my production deployment workflow:
#!/bin/bash
# Generate clean file list
find . -type f -mtime -14 -printf '%P\\n' > /tmp/deploy.txt
# Deployment loop
BETA_DIR="/home/user/beta/public_html"
PROD_DIR="/home/user/public_html"
while read -r file; do
if [[ -f "$BETA_DIR/$file" ]]; then
cp -i "$BETA_DIR/$file" "$PROD_DIR/$file"
echo "Deployed: $file"
else
echo "Warning: $file not found in beta" >&2
fi
done < /tmp/deploy.txt
# Clean up
rm /tmp/deploy.txt
For more robust handling, consider these improvements:
# Skip directories accidentally captured
find . -type f -mtime -14 ! -path "./.*" -printf '%P\\n'
# Exclude specific directories
find . -type f -mtime -14 ! -path "./node_modules/*" -printf '%P\\n'
For large codebases, these optimizations help:
# Use parallel processing with xargs
find . -type f -mtime -14 -print0 | sed -z 's|^\./||' | xargs -0 -P4 -I{} cp -i "$BETA_DIR/{}" "$PROD_DIR/{}"
When automating file deployments between environments, we often need to process find
command output that includes relative paths (./
prefix). Here's how to clean this up for reliable script execution.
For processing find
output, we have several effective approaches:
# Using basename in a while loop
find . -type f -mtime -14 | while read -r file; do
echo "$(basename "$file")"
done > deploy.txt
# Using parameter expansion (faster)
find . -type f -mtime -14 | while read -r file; do
echo "${file##*/}"
done > deploy.txt
Here's a robust implementation that handles filenames with spaces and special characters:
#!/bin/bash
# Generate clean file list
find . -type f -mtime -14 -print0 | while IFS= read -r -d '' file; do
echo "${file#*/}"
done > deploy.txt
# Deployment loop
while IFS= read -r -d '' file; do
cp -iv "/home/user/beta/public_html/${file}" "/home/user/public_html/${file}"
done < <(find . -type f -mtime -14 -print0 | sed 's|^\./||')
For complex deployments, consider these enhancements:
# Exclude certain directories
find . -type f -mtime -14 ! -path "./cache/*" ! -path "./tmp/*" | sed 's|^\./||'
# Add timestamp logging
find . -type f -mtime -14 -printf "%TY-%Tm-%Td %TH:%TM %p\n" | awk '{sub(/^\.\//, ""); print}'
For better performance with large file sets:
find . -type f -mtime -14 -print0 | sed -z 's|^\./||' | xargs -0 -I {} cp -iv \
"/home/user/beta/public_html/{}" "/home/user/public_html/{}"